Modulare Inverse berechnen


16

Bei zwei positiven Zahlen xund nmitx<2^nSchreiben Sie bei die kürzestmögliche zu berechnende Funktion x^-1 mod 2^n. Mit anderen Worten, finde yso etwas x*y=1 mod 2^n.

Ihre Funktion muss mindestens in einer angemessenen Zeit abgeschlossen sein n=64, damit eine umfassende Suche nicht funktioniert.

Wenn die Umkehrung nicht existiert, müssen Sie dies dem Aufrufer irgendwie anzeigen (eine Ausnahme auslösen, einen Sentinel-Wert zurückgeben usw.).

Wenn Sie sich fragen, wo Sie anfangen sollen, probieren Sie den erweiterten euklidischen Algorithmus .


Dies wird eine einzelne Aussage in einigen Mathe-Software sein
st0le

1
@ st0le: Richtig, und Sie könnten eine solche Funktion in solchen Systemen nicht verwenden. :-D
Chris Jester-Young

Antworten:


2

Python 95 89

cist deine Funktion. Gibt 0 zurück, wenn es keine Inverse gibt (dh wenn x gerade ist).

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 Bytes

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

Dies gibt 0 für gerade x zurück . Es verwendet den Satz von Euler mit der Beobachtung, dass 2 ^ n - 1 durch 2 ^ ( n - 1) - 1 durch die in Python eingebaute schnelle modulare Exponentiation teilbar ist. Dies ist schnell genug für n bis zu 7000 oder so, wo es mehr als eine Sekunde dauert.


2

Mathematica - 22

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

f[x,n]kehrt ymit x*y=1 mod 2^n, sonstx is not invertible modulo 2^n


2

GolfScript (23 Zeichen)

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

Das Sentinel-Ergebnis für eine nicht vorhandene Inverse ist 0 .

Dies ist eine einfache Anwendung des Satzes von Euler . , also x - 1x 2 n - 1 - 1xφ(2n)1(mod2n)x1x2n11(mod2n)

Leider ist das eine zu große Exponentialgröße, um sie direkt berechnen zu können. Daher müssen wir eine Schleife verwenden und innerhalb der Schleife eine modulare Reduktion durchführen. Der iterative Schritt ist und wir haben die Wahl des Basisfalls: entweder mitx2k1=(x2k11)2×xk=1

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

oder k=2mit

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

Ich arbeite an einem anderen Ansatz, aber der Sentinel ist schwieriger.

Die Schlüsselbeobachtung ist, dass wir die Inverse Stück für Stück aufbauen können: wenn xy1(mod2k1)xy{1,1+2k1}(mod2k)xx(y+xy1)1(mod2k)y=(x+1)y-1

0x1(mod20)

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

x+1 ist.

Das gibt die 19-Zeichen-Funktion

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

xx&11

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

02n-1 , aber ich habe das noch nicht bewiesen.

01-(x+1)n1-1n

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

nn x f

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

1

Ruby - 88 Zeichen

Nutzen Sie die Funktion 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

Einfach die rekursive Funktion von der verknüpften Wiki-Seite gibt bei einem Fehler 0 zurück.


Sie können einige Zeichen speichern, indem Sie e: einfügen (e=->a,b{...})[x,2**n][0]. Kann auch ein Zeichen durch Testen a%b<1statt speichern a%b==0.
Histokrat


1

Pyth , 9 Bytes

.^Et^2Q^2

Probieren Sie es hier aus!

Nimmt die Eingabe in umgekehrter Reihenfolge vor. Oder 9 Bytes zu: .^EtK^2QK.

Erläuterung

. ^ Et ^ 2Q ^ 2 - Volles Programm.

. ^ - Pow-Funktion. Das selbe in Python (pow).
  E - Die zweite Eingabe.
    ^ 2Q - und 2 ^ erste Eingabe.
   t - dekrementiert.
       ^ 2 - Und 2 ^ erstmal nochmal eingeben.

0

GAP, 39 Bytes

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

f(x,n)Gibt die Umkehrung von xModulo zurück 2^nund gibt eine Fehlermeldung aus

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

wenn keine Inverse existiert.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.