Oblicz odwrotność modularną


16

Biorąc pod uwagę dwie liczby dodatnie xi za npomocą x<2^n, napisz najkrótszą możliwą funkcję do obliczenia x^-1 mod 2^n. Innymi słowy, znajdź ytaki, że x*y=1 mod 2^n.

Twoja funkcja musi zostać ukończona przynajmniej w rozsądnym czasie n=64, aby wyczerpujące wyszukiwanie nie zadziałało.

Jeśli odwrotność nie istnieje, musisz jakoś to wskazać dzwoniącemu (wyrzuć wyjątek, zwróć wartość wartownika itp.).

Jeśli zastanawiasz się, od czego zacząć, wypróbuj rozszerzony algorytm euklidesowy .


będzie to pojedyncze stwierdzenie w niektórych programach matematycznych
st0le,

1
@ st0le: Racja, a nie można używać takiej funkcji w takich systemach. :-D
Chris Jester-Young

Odpowiedzi:


2

Python 95 89

cjest twoją funkcją. Zwraca 0, jeśli nie ma odwrotności (tj. Gdy x jest parzyste).

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 bajtów

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

Zwraca 0 dla parzystego x . Wykorzystuje twierdzenie Eulera, z obserwacją, że 2 ^ n - 1 można podzielić przez 2 ^ ( n - 1) - 1, za pomocą wbudowanego szybkiego modularnego potęgowania Pythona. Jest mnóstwo wystarczająco szybki dla n do 7000 lub tak, gdzie zaczyna robić więcej niż około sekundy.


2

Mathematica - 22

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

f[x,n]zwraca yz x*y=1 mod 2^n, w przeciwnym raziex is not invertible modulo 2^n


2

GolfScript (23 znaki)

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

Wynik wartownika dla nieistniejącej odwrotności to 0 .

Jest to proste zastosowanie twierdzenia Eulera . , więc x - 1x 2 n - 1 - 1xφ(2n)1(mod2n)x1x2n11(mod2n)

Niestety jest to zbyt duża wykładnicza wartość, aby obliczyć bezpośrednio, więc musimy użyć pętli i dokonać modularnej redukcji w pętli. Krok iteracyjny to i mamy do wyboru wariant podstawowy: albo zx2k1=(x2k11)2×xk=1

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

lub k=2z

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

Pracuję nad innym podejściem, ale wartownik jest trudniejszy.

Kluczową obserwacją jest to, że możemy budować odwrotność w górę krok po kroku: jeśli a następnie x y { 1 , 1 + 2 k - 1 }xy1(mod2k1) , a jeśli x jest nieparzyste, mamy x ( y + x y - 1 ) 1xy{1,1+2k1}(mod2k)x . (Jeśli nie jesteś przekonany, sprawdź oba przypadki osobno). Możemy więc zacząć od dowolnego odpowiedniego przypadku podstawowego i zastosować transformację y = ( x + 1 ) y - 1x(y+xy1)1(mod2k)y=(x+1)y1 odpowiednią liczbę razy.

Ponieważ otrzymujemy przez indukcję0x1(mod20)

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

gdzie odwrotność jest sumą sekwencji geometrycznej. Pokazałem wyprowadzenie, aby uniknąć efektu królika poza kapeluszem: biorąc pod uwagę to wyrażenie, łatwo to zauważyć (biorąc pod uwagę, że wartość w nawiasach kwadratowych jest liczbą całkowitą, która wynika z jego wyprowadzenia jako sumy liczby całkowitej sekwencja) produkt po lewej musi być w odpowiedniej klasie równoważności, jeśli jest parzyste.x+1

To daje funkcję 19-znakową

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

która daje poprawne odpowiedzi dla danych wejściowych, które mają odwrotność. Jednak nie jest to takie proste, gdy jest parzyste. Jedną potencjalnie interesującą opcją, którą znalazłem, jest dodanie zamiast .xx&11

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

02n1 , ale jeszcze tego nie udowodniłem.

01(x+1)n11n

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

nn x f

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

1

Ruby - 88 znaków

Użyj funkcji 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

Po prostu funkcja rekurencyjna z połączonej strony wiki zwraca 0 w przypadku błędu.


Można zapisać kilka znaków, których autorem jest inline e: (e=->a,b{...})[x,2**n][0]. Może także zapisać postać, testując a%b<1zamiast a%b==0.
histocrat


1

Pyth , 9 bajtów

.^Et^2Q^2

Wypróbuj tutaj!

Pobiera dane wejściowe w odwrotnej kolejności. Lub 9 bajtów za: .^EtK^2QK.

Wyjaśnienie

. ^ Et ^ 2Q ^ 2 - Pełny program.

. ^ - Funkcja Pow. To samo w Pythonie (pow).
  E - Drugie wejście.
    ^ 2Q - I 2 ^ pierwsze wejście.
   t - Zmniejszony.
       ^ 2 - I 2 ^ ponownie pierwsze wejście.

0

GAP, 39 bajtów

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

f(x,n)zwraca odwrotność xmodulo 2^ni wyświetla komunikat o błędzie

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

jeśli nie istnieje odwrotność.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.