Calcola l'inverso modulare


16

Dati due numeri positivi xe ncon x<2^n, scrivere la funzione più breve possibile per calcolare x^-1 mod 2^n. In altre parole, trova ytale x*y=1 mod 2^n.

La tua funzione deve essere completata in un tempo ragionevole per almeno n=64, quindi la ricerca esaustiva non funzionerà.

Se l'inverso non esiste, è necessario indicarlo in qualche modo al chiamante (generare un'eccezione, restituire un valore sentinella, ecc.).

Se ti stai chiedendo da dove cominciare, prova l' algoritmo euclideo esteso .


questa sarà una singola affermazione in alcuni software di matematica
via

1
@ st0le: giusto, e non ti sarebbe permesso usare una tale funzione in tali sistemi. MrGreen
Chris Jester-Young,

Risposte:


2

Python 95 89

cè la tua funzione. Restituisce 0 se non è presente alcun valore inverso (ovvero quando x è pari).

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 byte

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

Questo restituisce 0 anche per x . Usa il teorema di Eulero, con l'osservazione che 2 ^ n - 1 è divisibile per 2 ^ ( n - 1) - 1, tramite la rapida esponenziazione modulare incorporata in Python. Questo è abbastanza veloce per n fino a 7000 o giù di lì, dove inizia a richiedere più di circa un secondo.


2

Mathematica - 22

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

f[x,n]ritorna ycon x*y=1 mod 2^n, altrimentix is not invertible modulo 2^n


2

GolfScript (23 caratteri)

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

Il risultato sentinella per un inverso inesistente è 0.

Questa è una semplice applicazione del teorema di Eulero . , quindi x - 1x 2 n - 1 - 1Xφ(2n)1(mod2n)X-1X2n-1-1(mod2n)

Sfortunatamente questo è un esponenziale piuttosto grande per il calcolo diretto, quindi dobbiamo usare un loop e fare una riduzione modulare all'interno del loop. Il passaggio iterativo è e abbiamo una scelta di caso base: oconX2K-1=(X2K-1-1)2×Xk=1

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

o k=2con

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

Sto lavorando ad un altro approccio, ma la sentinella è più difficile.

L'osservazione chiave è che possiamo costruire l'inverso a poco a poco: se Xy1(mod2K-1)Xy{1,1+2K-1}(mod2K)XX(y+Xy-1)1(mod2K)y'=(X+1)y-1

0X1(mod20)

X(1-(X+1)nX)1(mod2n)

X+1 è pari.

Questo dà la funzione di 19 caratteri

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

Xx&11

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

02n-1 , ma non l'ho ancora dimostrato.

01-(X+1)n1-1n

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

nn x f

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

1

Rubino - 88 caratteri

Utilizzare la funzione 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

Semplicemente la funzione ricorsiva dalla pagina wiki collegata, restituisce 0 in caso di errore.


È possibile salvare alcuni personaggi di inlining e: (e=->a,b{...})[x,2**n][0]. Puoi anche salvare un personaggio testando a%b<1invece di a%b==0.
histocrat,


1

Pyth , 9 byte

.^Et^2Q^2

Provalo qui!

Accetta l'input in ordine inverso. Oppure, 9 byte troppo: .^EtK^2QK.

Spiegazione

. ^ Et ^ 2Q ^ 2 - Programma completo.

. ^ - Funzione Pow. Lo stesso in Python (pow).
  E - Il secondo ingresso.
    ^ 2Q - E 2 ^ primo input.
   t - Decrementato.
       ^ 2 - E 2 ^ primo input di nuovo.

0

GAP, 39 byte

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

f(x,n)restituisce l'inverso del xmodulo 2^ne fornisce un messaggio di errore

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

se non esiste un contrario.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.