Tính toán nghịch đảo mô-đun


16

Cho hai số dương xnvới x<2^n, hãy viết hàm ngắn nhất có thể để tính x^-1 mod 2^n. Nói cách khác, tìm ynhư vậy x*y=1 mod 2^n.

Chức năng của bạn phải hoàn thành trong một thời gian hợp lý ít nhất n=64, vì vậy tìm kiếm toàn diện sẽ không hoạt động.

Nếu nghịch đảo không tồn tại, bạn phải chỉ ra điều đó cho người gọi bằng cách nào đó (ném ngoại lệ, trả về giá trị sentinel, v.v.).

Nếu bạn đang tự hỏi nên bắt đầu từ đâu, hãy thử Thuật toán Euclide mở rộng .


đây sẽ là một tuyên bố duy nhất trong một số phần mềm toán học
st0le

1
@ st0le: Phải, và bạn sẽ không được phép sử dụng chức năng như vậy trong các hệ thống như vậy. :-D
Chris Jester-Young

Câu trả lời:


2

Con trăn 95 89

clà chức năng của bạn. Trả về 0 nếu không có nghịch đảo (tức là khi x chẵn).

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)

Điều này trả về 0 cho x chẵn . Nó sử dụng định lý Euler, với quan sát rằng 2 ^ n - 1 chia hết cho 2 ^ ( n - 1) - 1, thông qua phép lũy thừa mô đun nhanh tích hợp của Python. Điều này đủ nhanh cho n lên đến 7000 hoặc hơn, trong đó nó bắt đầu mất nhiều hơn khoảng một giây.


2

Toán học - 22

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

f[x,n]trả lại yvới x*y=1 mod 2^n, nếu khôngx is not invertible modulo 2^n


2

GolfScript (23 ký tự)

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

Kết quả sentinel cho một nghịch đảo không tồn tại là 0.

Đây là một ứng dụng đơn giản của định lý Euler . , do đó x - 1x 2 n - 1 - 1xφ(2n)1(mod2n)x-1x2n-1-1(mod2n)

Thật không may, đó là một số mũ quá lớn để tính toán trực tiếp, vì vậy chúng ta phải sử dụng một vòng lặp và thực hiện giảm mô-đun bên trong vòng lặp. Bước lặp là và chúng ta có một sự lựa chọn về trường hợp cơ sở: hoặc vớix2k-1= =(x2k-1-1)2×xk=1

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

hoặc k=2với

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

Tôi đang làm việc theo một cách tiếp cận khác, nhưng việc canh gác khó khăn hơn.

Các quan sát quan trọng là chúng ta có thể xây dựng các nghịch đảo lên từng chút một: nếu thì x y { 1 , 1 + 2 k - 1 }xy1(mod2k-1) , và nếu x là số lẻ chúng ta có x ( y + x y - 1 ) 1xy{1,1+2k-1}(mod2k)x . (Nếu bạn không bị thuyết phục, hãy kiểm tra hai trường hợp riêng biệt). Vì vậy, chúng ta có thể bắt đầu tại bất kỳ trường hợp cơ sở phù hợp nào và áp dụng phép biến đổi y = ( x + 1 ) y - 1 một số lần thích hợp.x(y+xy-1)1(mod2k)y'= =(x+1)y-1

Kể từ chúng tôi nhận được, bằng cảm ứng0x1(mod20)

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

x+1 là chẵn.

Điều đó mang lại cho chức năng 19 char

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

xx&11

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

02n-1 , nhưng tôi chưa chứng minh điều đó.

01-(x+1)n1-1n

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

nn x f

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

1

Ruby - 88 ký tự

Sử dụng chức năng 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

Đơn giản là hàm đệ quy từ trang wiki được liên kết, trả về 0 do lỗi.


Bạn có thể lưu một số ký tự bằng cách nội tuyến e : (e=->a,b{...})[x,2**n][0]. Cũng có thể lưu một nhân vật bằng cách thử nghiệm a%b<1thay vì a%b==0.
lịch sử


1

Bình thường , 9 byte

.^Et^2Q^2

Hãy thử nó ở đây!

Đưa đầu vào theo thứ tự ngược lại. Hoặc, 9 byte quá : .^EtK^2QK.

Giải trình

. ^ Et ^ 2Q ^ 2 - Chương trình đầy đủ.

. ^ - Hàm Pow. Tương tự trong Python (pow).
  E - Đầu vào thứ hai.
    ^ 2Q - Và 2 ^ đầu vào đầu tiên.
   t - Giảm dần.
       ^ 2 - Và 2 ^ lần đầu tiên nhập lại.

0

GAP, 39 byte

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

f(x,n)trả về nghịch đảo của xmodulo 2^nvà đưa ra thông báo lỗi

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

nếu không tồn tại nghịch đảo.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.