Вычислить модульное обратное


16

Учитывая два положительных числа xи nс x<2^n, напишите кратчайшую возможную функцию для вычисления x^-1 mod 2^n. Другими словами, найти yтакое, что x*y=1 mod 2^n.

Ваша функция должна быть выполнена в разумные сроки, по крайней мере n=64, поэтому исчерпывающий поиск не будет работать.

Если обратного не существует, вы должны как-то указать это вызывающей стороне (сгенерировать исключение, вернуть значение часового и т. Д.).

Если вам интересно, с чего начать, попробуйте расширенный евклидов алгоритм .


это будет одно утверждение в некоторых математических программах
st0le

1
@ st0le: Правильно, и вам не разрешат использовать такую ​​функцию в таких системах. :-D
Крис Шестер-Янг

Ответы:


2

Python 95 89

cэто ваша функция. Возвращает 0, если обратного нет (т. Е. Когда x четно).

p=lambda x,y,m:y and p(x,y/2,m)**2*x**(y&1)%m or 1
c=lambda x,n:[0,p(x,2**n-1,2**n)][x%2]

3

Python, 29 байт

lambda x,n:pow(x,2**n-1,2**n)

Это возвращает 0 для четного х . Он использует теорему Эйлера с наблюдением, что 2 ^ n - 1 делится на 2 ^ ( n - 1) - 1 через встроенное быстрое модульное возведение в степень Python. Это достаточно быстро для n до 7000 или около того, где это занимает более секунды.


2

Mathematica - 22

f=PowerMod[#,-1,2^#2]&

f[x,n]возвращается yс x*y=1 mod 2^n, в противном случаеx is not invertible modulo 2^n


2

GolfScript (23 символа)

{:^((1${\.**2^?%}+*}:f;

Часовой результат для несуществующего обратного равен 0.

Это простое применение теоремы Эйлера . , поэтому x - 1x 2 n - 1 - 1xφ(2n)1(mod2n)x1x2n11(mod2n)

К сожалению, это слишком большая экспонента, чтобы вычислять напрямую, поэтому мы должны использовать цикл и выполнять модульное сокращение внутри цикла. Итерационный шаг и у нас есть выбор базового случая: либо сx2k1=(x2k11)2×xk=1

{1\:^(@{\.**2^?%}+*}:f;

или k=2с

{:^((1${\.**2^?%}+*}:f;

Я работаю над другим подходом, но стражу сложнее.

Ключевое наблюдение заключается в том, что мы можем построить обратный шаг за шагом: если xy1(mod2k1)xy{1,1+2k1}(mod2k)xx(y+xy1)1(mod2k)y=(x+1)y1

0x1(mod20)

x(1(x+1)nx)1(mod2n)

x+1

Это дает функцию 19 символов

{1$)1$?@/~)2@?%}:f;

Иксx&11

{1$.1&+1$?@/~)2@?%}:f;

02n1

01(x+1)n11n

{1$.1&*)1$?@/~)2@?%}:f;

nn x f

{..1&*)2$?\/~)2@?%}:f;

1

Рубин - 88 символов

Используйте функцию f.

def e a,b;a%b==0?[0,1]:(x,y=e(b,a%b);[y,x-(y*(a/b))])end
def f x,n;e(x,2**n)[0]*(x%2)end

Просто рекурсивная функция со связанной вики-страницы возвращает 0 при ошибке.


Вы можете сохранить некоторые символы от встраивания е: (e=->a,b{...})[x,2**n][0]. Можно также сохранить персонажа, протестировав a%b<1вместо a%b==0.
гистократ


1

Pyth , 9 байт

.^Et^2Q^2

Попробуй это здесь!

Принимает ввод в обратном порядке. Или, 9 байт тоже: .^EtK^2QK.

объяснение

. ^ Et ^ 2Q ^ 2 - Полная программа.

. ^ - Функция Пау. То же самое в Python (Pow).
  E - Второй вход.
    ^ 2Q - И 2 ^ первый ввод.
   т - уменьшено.
       ^ 2 - И 2 ^ первый ввод снова.

0

GAP, 39 байт

f:=function(x,n)return 1/x mod 2^n;end;

f(x,n)возвращает инверсию по xмодулю 2^nи выдает сообщение об ошибке

Error, ModRat: for <r>/<s> mod <n>, <s>/gcd(<r>,<s>) and <n> must be coprime

если обратного не существует.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.