Mô đun nghịch đảo nhân


22

Nhiệm vụ của bạn là đưa ra hai số nguyên abtính toán nghịch đảo mô đun của mô đun b, nếu nó tồn tại.

Mô-đun nghịch đảo của amodulo blà một số cnhư vậy ac ≡ 1 (mod b). Số này là modulo duy nhất bcho bất kỳ cặp ab. Nó chỉ tồn tại nếu ước số chung lớn nhất của ab1.

Các trang Wikipedia cho nghịch đảo mô-đun có thể được tư vấn nếu bạn cần thêm thông tin về chủ đề.

Đầu vào và đầu ra

Đầu vào được đưa ra dưới dạng hai số nguyên hoặc danh sách hai số nguyên. Chương trình của bạn sẽ xuất ra một số duy nhất, nghịch đảo nhân mô-đun trong khoảng 0 < c < bhoặc giá trị cho biết không có nghịch đảo. Giá trị có thể là bất cứ thứ gì, ngoại trừ một số trong phạm vi (0,b)và cũng có thể là một ngoại lệ. Tuy nhiên, giá trị phải giống nhau đối với các trường hợp không có nghịch đảo.

0 < a < b có thể được giả định

Quy tắc

  • Chương trình sẽ kết thúc tại một số điểm và sẽ giải quyết từng trường hợp thử nghiệm trong vòng chưa đầy 60 giây
  • Áp dụng sơ hở tiêu chuẩn

Các trường hợp thử nghiệm

Các trường hợp thử nghiệm dưới đây được đưa ra trong định dạng, a, b -> output

1, 2 -> 1
3, 6 -> Does not exist
7, 87 -> 25
25, 87 -> 7
2, 91 -> 46
13, 91 -> Does not exist
19, 1212393831 -> 701912218
31, 73714876143 -> 45180085378
3, 73714876143 -> Does not exist

Chấm điểm

Đây là mã golf, vì vậy mã ngắn nhất cho mỗi ngôn ngữ sẽ thắng.

Đâyđây là những câu hỏi tương tự, nhưng cả hai đều yêu cầu các tình huống cụ thể.


6
Theo Định lý nhỏ của Fermat rằng nghịch đảo nhân của a, nếu nó tồn tại, có thể được tính toán hiệu quả như một ^ (phi (b) -1) mod b, trong đó phi là hàm tổng số của Euler: phi (p0 ^ k0 * p1 ^ k1 * ...) = (p0-1) * p0 ^ (k0-1) * (p1-1) * p1 ^ (k1-1) * ... Không nói rằng nó dẫn đến mã ngắn hơn :)
ngn

1
@Jenny_mathy Lấy đầu vào bổ sung thường không được phép.
Ông Xcoder

3
Tôi đếm sáu câu trả lời dường như bị ép buộc và không thể chạy tất cả các trường hợp kiểm tra trong 60 giây (một số trong số đó đưa ra lỗi ngăn xếp hoặc bộ nhớ trước).
Ørjan Johansen

1
@ngn: Bạn đã kết hợp Định lý nhỏ của Fermat (FLT) với sự cải tiến của Euler. Fermat không biết về hàm Euler phi. Hơn nữa, cải tiến FLT và Euler chỉ áp dụng nếu gcd (a, b) = 1. Cuối cùng, ở dạng bạn đã viết, "a ^ (\ phi (b) -1) mod b" phù hợp với 1, không phải là a ^ (- 1). Để có được ^ (- 1), hãy sử dụng mod ^ (\ phi (b) -2) b.
Tháp Eric

1
@EricTowers Euler's là một hệ quả. Về "gcd (a, b) = 1" - Tôi đã nói "nếu nó [nghịch đảo] tồn tại". Bạn có chắc về phi (b) -2 không?
ngn

Câu trả lời:


11

Toán học, 14 byte

Nội dung bắt buộc Mathicala :

ModularInverse

Đây là một hàm có hai đối số ( ab) và trả về nghịch đảo của mod b nếu nó tồn tại. Nếu không, nó trả về lỗi ModularInverse: a is not invertible modulo b..


7

JavaScript (ES6), 79 73 62 61 byte

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

Nó sử dụng thuật toán Euclide mở rộng và giải quyết tất cả các trường hợp thử nghiệm gần như ngay lập tức.

f=(a,b,c=!(n=b),d=1)=>a?f(b%a,a,d,c-(b-b%a)/a*d):b<2&&(c+n)%n

Các trường hợp thử nghiệm


Tại sao không thể viết tên của hàm f, như trong f (c, a, b = 0, d = 1, n = a) => c? F (a% c, c, d, b- ( aa% c) / c * d, n): a <2 && (b + n)% n?
RosLuP

@RosLup f(x,y)luôn được phân tích cú pháp như một lời gọi hàm, trừ khi nó được đặt trước functiontừ khóa một cách rõ ràng . Mặt khác, một hàm mũi tên ẩn danh được khai báo là (x,y)=>somethingf=(x,y)=>somethinggán hàm cho fbiến.
Arnauld

4

Thạch , 2 byte

æi

Hãy thử trực tuyến!

Điều này sử dụng một nội trang cho nghịch đảo mô-đun và trả về 0 cho không nghịch đảo mô-đun.

Thạch , 7 byte

R×%⁸’¬T

Hãy thử trực tuyến!

Đầu ra tập rỗng (được biểu diễn dưới dạng chuỗi rỗng) không có nghịch đảo mô-đun. Hết bộ nhớ trên TIO cho các trường hợp thử nghiệm lớn nhất, nhưng sẽ hoạt động khi có đủ bộ nhớ.

Làm thế nào nó hoạt động

R×%⁸’¬T  
R        Generate range of b
 ×       Multiply each by a
  %⁸     Mod each by b
    ’    Decrement (Map 1 to 0 and all else to truthy)
     ¬   Logical NOT
      T  Get the index of the truthy element.

Nếu bạn muốn làm việc cho các trường hợp thử nghiệm lớn hơn, hãy thử phiên bản (tương đối vô văn hóa) này, đòi hỏi nhiều thời gian hơn là bộ nhớ:

Thạch, 9 byte

×⁴%³’¬ø1#

Hãy thử trực tuyến!

Làm thế nào nó hoạt động

×⁴%³’¬ø1#
        #   Get the first
      ø1      one integer
            which meets:
×⁴            When multiplied by a
  %³          And modulo-d by b
    ’         Decrement
     ¬        Is falsy

4

Python 2 , 34 byte

f=lambda a,b:a==1or-~b*f(-b%a,a)/a

Hãy thử trực tuyến!

Hàm đệ quy cung cấp cho Truecho print f(1,2), mà tôi tin là chấp nhận được, và các lỗi cho các đầu vào không hợp lệ.

Chúng tôi đang cố gắng tìm x trong ax1(modb) .

ax1=kbk

Lấy moda1kb(moda)kb1(moda)k

kf(b%a,a)

aab

kax1=kbxkb+1a


3

R + số , 15 byte

numbers::modinv

Trả về NAcho những người akhông có mod đảo ngược b.

R-Fiddle để thử nó!

R , 33 byte (không cạnh tranh)

Điều này sẽ thất bại rất lớn bvì nó thực sự tạo ra một vectơ kích thước 32*bbit.

function(a,b)which((1:b*a)%%b==1)

Hãy thử trực tuyến!

Trả về integer(0)(một danh sách trống) cho những người akhông có mod đảo ngược b.


3

Toán học, 18 byte

PowerMod[#,-1,#2]&

đầu vào

[31, 73714876143]


3

Python 2 , 51 49 54 53 51 49 byte

-1 byte nhờ chính thức
-1 byte nhờ Shaggy

a,b=input()
i=a<2
while(a*i%b-1)*b%a:i+=1
print+i

Hãy thử trực tuyến!

In 0khi không có giải pháp.


1
Đầu ra 0cho a=1b=2; từ các trường hợp thử nghiệm, nó sẽ xuất ra 1.
Xù xì


1
Như Shaggy đã chỉ ra, thất bại cho2, 1
Ông Xcoder

@Shaggy nên hoạt động ngay bây giờ
Rod

Điều này không trả lại câu trả lời trong 60 giây (trên TIO) cho đầu vào 31,73714876143.
Ilmari Karonen

3

Japt , 9 8 byte

Đưa các đầu vào theo thứ tự ngược lại. Đầu ra -1không khớp. Craps out như số nguyên lớn hơn được lớn hơn.

Ç*V%UÃb1

Kiểm tra nó

  • Đã lưu 1 byte nhờ ETH chỉ ra một khoảng trống, và rất rõ ràng, không gian.

Đầu vào thử nghiệm 73714876143,31dường như tạo ra lỗi hết bộ nhớ trên Firefox (và làm hỏng Chromium). Tôi không nghĩ rằng đây là một câu trả lời hợp lệ.
Ilmari Karonen

@IlmariKaronen: Tôi đã chỉ ra rõ ràng thực tế đó trong giải pháp của tôi. Chúng ta có thể giả sử bộ nhớ vô hạn cho các mục đích của mã golf để các vấn đề và sự cố bộ nhớ không làm mất hiệu lực giải pháp này.
Xù xì

1
Thật không may, các vấn đề về bộ nhớ cũng khiến bạn không thể biết liệu mã của mình có thực sự giải quyết các trường hợp thử nghiệm trong 60 giây theo quy định của thử thách hay không. Tôi nghi ngờ điều đó sẽ không xảy ra, ngay cả khi có đủ bộ nhớ để làm cho nó không bị sập, nhưng nếu không có máy tính thực sự có thể chạy chương trình trong một thời gian dài thì không có cách nào để chắc chắn.
Ilmari Karonen


2

Python 3 , 49 byte

lambda a,b:[c for c in range(b)if-~c*a%b==1][0]+1

Hãy thử trực tuyến!

Python 3 , 50 byte

lambda a,b:[c for c in range(1,b+1)if c*a%b==1][0]

Hãy thử trực tuyến!

Điều này ném IndexError: list index out of rangetrong trường hợp không có nghịch đảo nhân mô-đun, vì nó được cho phép bởi các quy tắc.


Điều này không trả về kết quả cho đầu vào sau 31,7371487614360 giây (trên TIO).
Ilmari Karonen

@IlmariKaronen Có vẻ như sẽ hoàn thành sau 56 giây trên máy của tôi (Macbook Pro '15)
Ông Xcoder

2

8 , 6 byte

invmod

Giải trình

invmodlà một từ thứ 8 tính giá trị nghịch đảo của amodulo b. Nó trở lạinull về lỗi tràn hoặc các lỗi khác.

Trường hợp sử dụng và kiểm tra

ok> 1 2 invmod .
1
ok> 3 6 invmod .
null
ok> 7 87 invmod .
25
ok> 25 87 invmod .
7
ok> 2 91 invmod .
46
ok> 13 91 invmod .
null
ok> 19 1212393831 invmod .
701912218
ok> 31 73714876143 invmod .
45180085378
ok> 3 73714876143 invmod .
null


2

J , 28 byte

4 :'(1=x+.y)*x y&|@^<:5 p:y'

Hãy thử trực tuyến!

Sử dụng định lý Euler . Trả về 0 nếu nghịch đảo không tồn tại.

Giải trình

4 :'(1=x+.y)*x y&|@^<:5 p:y'  Input: a (LHS), b (RHS)
4 :'                       '  Define an explicit dyad - this is to use the special
                              form `m&|@^` to perform modular exponentiation
                          y   Get b
                      5 p:    Euler totient
                    <:        Decrement
             x                Get a
                   ^          Exponentiate
               y&|@             Modulo b
       x+.y                   GCD of a and b
     1=                       Equals 1
            *                 Multiply

2

Bình thường , 10 byte

3 byte được lưu nhờ @Jakube .

xm%*szdQQ1

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

Trả về -1 không có nghịch đảo nhân.

Sự cố mã

xm%*szdQQ1      Let Q be the first input.
 m      Q       This maps over [0 ... Q) with a variable d.
   *szd         Now d is multiplied by the evaluated second input.
  %    Q        Now the remained modulo Q is retrieved.
x        1      Then, the first index of 1 is retrieved from that mapping.

Bình thường , 15 13 byte

KEhfq1%*QTKSK

Ném một ngoại lệ trong trường hợp không tồn tại nghịch đảo nhân.

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

Bình thường , 15 byte

Iq1iQKEfq1%*QTK

Điều này thêm rất nhiều byte để xử lý trường hợp không có số đó. Chương trình có thể được rút ngắn đáng kể nếu trường hợp đó không cần xử lý:

fq1%*QTK

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


2 byte được lưu vớiKExm%*QdKK1
Jakube

Hoặc 3 byte nếu bạn trao đổi thứ tự đầu vào:xm%*szdQQ1
Jakube

@Jakube Cảm ơn rất nhiều, chỉnh sửa!
Ông Xcoder

Cái này hoạt động ra sao?
Kritixi Lithos

@Cowsquack Tôi đã thêm một sự cố mã hoàn toàn nguyên thủy nhưng tôi không có thời gian để đưa ra một lời giải thích hoàn chỉnh. Hy vọng rằng bây giờ nó đã đủ rõ ràng nhưng tôi sẽ cố gắng thêm một lời giải thích đầy đủ hơn sớm.
Ông Xcoder

1

C (gcc) , 115 byte

#define L long long
L g(L a,L b,L c,L d){return a?g(b%a,a,d-b/a*c,c):b-1?0:d;}L f(L a,L b){return(g(a,b,1,0)+b)%b;}

Hãy thử trực tuyến!

Thuật toán Euclide mở rộng, phiên bản đệ quy

C (gcc) , 119 byte

long long f(a,b,c,d,t,n)long long a,b,c,d,t,n;{for(c=1,d=0,n=b;a;a=t)t=d-b/a*c,d=c,c=t,t=b%a,b=a;return b-1?0:(d+n)%n;}

Hãy thử trực tuyến!

Thuật toán Euclide mở rộng, phiên bản lặp


1

C (gcc) , 48 110 104 byte

#define f(a,b)g(a,b,!b,1,b)
long g(a,b,c,d,n)long a,b,c,d,n;{a=a?g(b%a,a,d,c-(b-b%a)/a*d):!--b*(c+n)%n;}

Hãy thử trực tuyến!

Điều này sẽ hoạt động với tất cả các đầu vào (phù hợp trong một thời gian dài) trong vòng 60 giây.

Chỉnh sửa. Tôi đã lạm dụng nbiến nên tôi cũng có thể giả sử rằng gcc đặt nhiệm vụ đầu tiên vào %rax.


1
Than ôi, điều này cho kết quả sai ngay cả đối với đầu vào khá nhỏ do tràn số nguyên bên trong vòng lặp. Ví dụ, f(3,1000001)trả về 717, rõ ràng là vô nghĩa (câu trả lời đúng là 333334). Ngoài ra, ngay cả khi lỗi này được khắc phục bằng cách sử dụng loại số nguyên rộng hơn, phương pháp tiếp cận mạnh mẽ này chắc chắn sẽ hết thời gian cho một số trường hợp thử nghiệm lớn hơn được đưa ra trong thử thách.
Ilmari Karonen


0

Tiên đề, 45 byte

f(x:PI,y:PI):NNI==(gcd(x,y)=1=>invmod(x,y);0)

0 cho lỗi khác trả về z với x * z Mod y = 1


0

Con trăn 2 , 52 byte

-3 byte nhờ ông Xcoder.

f=lambda a,b,i=1:i*a%b==1and i or i<b and f(a,b,i+1)

Hãy thử trực tuyến!

Đầu ra Falsekhông có giải pháp và lỗi khi blớn hơn.

TIO nhúng

Tôi chỉ đang thử nghiệm iframe trong Stack Snippets và chúng hoạt động hoàn toàn tuyệt vời.


Tôi không chắc chắn điều này hoạt động, không i*a%bthể 0?
Thuật sĩ lúa mì

Lỗi với lỗi "vượt quá độ sâu đệ quy tối đa" cho đầu vào (31,73714876143).
Ilmari Karonen

0

JavaScript (ES6), 42 41 39 38 byte

Đầu ra falsekhông khớp. Sẽ ném một lỗi tràn khi số thứ hai trở nên quá lớn.

x=>y=>(g=z=>x*z%y==1?z:z<y&&g(++z))(1)

0

Thạch , 27 byte

²%³
⁴Ç⁹Сx⁸
ÆṪ’BṚçL$P%³×gỊ¥

Hãy thử trực tuyến!

Sử dụng định lý Euler với lũy thừa mô-đun. Vì Jelly không có tích hợp để thực hiện lũy thừa mô-đun, nên nó phải được thực hiện và phải mất hầu hết các byte.


0

Tiên đề, 99 byte

w(a,b,x,u)==(a=0=>(b*b=1=>b*x;0);w(b rem a,a,u,x-u*(b quo a)));h(a,b)==(b=0=>0;(b+w(a,b,0,1))rem b)

nó sử dụng hàm h (); h (a, b) return 0 nếu lỗi [không tồn tại nghịch đảo] nếu không, nó trả về z sao cho a * z mod b = 1 Điều này sẽ ổn ngay cả khi đối số là âm ...

đây sẽ là hàm egcd () chung trả về danh sách int (vì vậy chúng cũng có thể âm)

egcd(aa:INT,bb:INT):List INT==
   x:=u:=-1   -- because the type is INT
   (a,b,x,u):=(aa,bb,0,1)
   repeat
      a=0=>break
      (q,r):=(b quo a, b rem a)
      (b,a,x,u):=(a,r,u,x-u*q)
   [b,x, (b-x*aa)quo bb]

đây là cách sử dụng nó

(7) -> h(31,73714876143)
   (7)  45180085378
                                                    Type: PositiveInteger

tôi tìm thấy thuật toán cơ bản trên internet từ https://pastebin.com/A13ybryc

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.