Hitung invers modular


16

Diberi dua angka positif xdan ndengan x<2^n, tulis fungsi sesingkat mungkin untuk dihitung x^-1 mod 2^n. Dengan kata lain, temukan yitu x*y=1 mod 2^n.

Fungsi Anda harus menyelesaikan setidaknya dalam waktu yang wajar n=64, sehingga pencarian lengkap tidak akan berfungsi.

Jika kebalikannya tidak ada, Anda harus menunjukkan itu kepada penelepon entah bagaimana (melemparkan pengecualian, mengembalikan nilai sentinel, dll).

Jika Anda bertanya-tanya harus mulai dari mana, coba Algoritma Euclidean Diperpanjang .


ini akan menjadi pernyataan tunggal dalam beberapa perangkat lunak matematika
st0le

1
@ st0le: Benar, dan Anda tidak akan diizinkan untuk menggunakan fungsi seperti itu dalam sistem tersebut. :-D
Chris Jester-Young

Jawaban:


2

Python 95 89

cadalah fungsi anda. Mengembalikan 0 jika tidak ada terbalik (yaitu ketika x genap).

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)

Ini mengembalikan 0 bahkan x . Ia menggunakan teorema Euler, dengan pengamatan bahwa 2 ^ n - 1 dapat habis dibagi 2 ^ ( n - 1) - 1, melalui eksponensial modular cepat built-in Python. Ini cukup cepat untuk n hingga 7000 atau lebih, di mana ia mulai mengambil lebih dari sekitar satu detik.


2

Mathematica - 22

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

f[x,n]kembali ydengan x*y=1 mod 2^n, jika tidakx is not invertible modulo 2^n


2

GolfScript (23 karakter)

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

Hasil sentinel untuk invers yang tidak ada adalah 0.

Ini adalah aplikasi sederhana dari teorema Euler . , jadi x - 1x 2 n - 1 - 1xφ(2n)1(mod2n)x1x2n11(mod2n)

Sayangnya itu eksponensial terlalu besar untuk dihitung secara langsung, jadi kita harus menggunakan loop dan melakukan reduksi modular di dalam loop. Langkah berulang adalah dan kami memiliki pilihan kasus dasar: baik denganx2k1=(x2k11)2×xk=1

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

atau k=2dengan

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

Saya sedang mengerjakan pendekatan lain, tetapi penjaga itu lebih sulit.

Pengamatan kuncinya adalah kita dapat membangun invers up sedikit demi sedikit: jika 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 genap.

Itu memberi fungsi 19-char

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

xx&11

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

02n-1 , tapi saya belum membuktikannya.

01(x+1)n11n

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

nn x f

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

1

Ruby - 88 karakter

Gunakan fungsinya 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

Cukup fungsi rekursif dari halaman wiki yang tertaut, mengembalikan 0 pada kesalahan.


Anda dapat menyimpan beberapa karakter dengan sebaris e: (e=->a,b{...})[x,2**n][0]. Dapat juga menyimpan karakter dengan menguji a%b<1alih-alih a%b==0.
histokrat


1

Pyth , 9 byte

.^Et^2Q^2

Coba di sini!

Mengambil input dalam urutan terbalik. Atau, 9 byte juga: .^EtK^2QK.

Penjelasan

. ^ Et ^ 2Q ^ 2 - Program lengkap.

. ^ - Fungsi Pow. Hal yang sama dengan Python (pow).
  E - Input kedua.
    ^ 2Q - Dan 2 ^ input pertama.
   t - Dikurangi.
       ^ 2 - Dan 2 ^ input pertama lagi.

0

GAP, 39 byte

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

f(x,n)mengembalikan kebalikan dari xmodulo 2^ndan memberikan pesan kesalahan

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

jika tidak ada terbalik.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.