Biorąc pod uwagę dwie liczby dodatnie x
i za n
pomocą x<2^n
, napisz najkrótszą możliwą funkcję do obliczenia x^-1 mod 2^n
. Innymi słowy, znajdź y
taki, ż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 .
Odpowiedzi:
Python
9589c
jest twoją funkcją. Zwraca 0, jeśli nie ma odwrotności (tj. Gdy x jest parzyste).źródło
Python, 29 bajtów
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.
źródło
Mathematica - 22
f[x,n]
zwracay
zx*y=1 mod 2^n
, w przeciwnym raziex is not invertible modulo 2^n
źródło
GolfScript (23 znaki)
Wynik wartownika dla nieistniejącej odwrotności to
0
.Jest to proste zastosowanie twierdzenia Eulera . , więc x - 1 ≡ x 2 n - 1 - 1xφ(2n)≡1(mod2n) x−1≡x2n−1−1(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 zx2k−1=(x2k−1−1)2×x
k=1
lub
k=2
zPracuję 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 }xy≡1(mod2k−1) , a jeśli x jest nieparzyste, mamy x ( y + x y - 1 ) ≡ 1xy∈{1,1+2k−1}(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+xy−1)≡1(mod2k) y′=(x+1)y−1 odpowiednią liczbę razy.
Ponieważ otrzymujemy przez indukcję0x≡1(mod20)
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ą
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 .x
x&1
1
n x f
źródło
Ruby - 88 znaków
Użyj funkcji
f
.Po prostu funkcja rekurencyjna z połączonej strony wiki zwraca 0 w przypadku błędu.
źródło
(e=->a,b{...})[x,2**n][0]
. Może także zapisać postać, testująca%b<1
zamiasta%b==0
.Haskell, 42 bajty
Wykorzystując algorytm oparty na lemacie Hensela, który podwaja liczbę cyfr w każdej iteracji, biegnie to w mniej niż sekundę dla n do około 30 milionów !
źródło
Pyth , 9 bajtów
Wypróbuj tutaj!
Pobiera dane wejściowe w odwrotnej kolejności. Lub 9 bajtów za:
.^EtK^2QK
.Wyjaśnienie
źródło
GAP, 39 bajtów
f(x,n)
zwraca odwrotnośćx
modulo2^n
i wyświetla komunikat o błędziejeśli nie istnieje odwrotność.
źródło