模乘逆


22

您的任务是给定两个整数,ab计算模b的模乘法乘法逆(如果存在)。

模的a模逆b是一个c这样的数字ac ≡ 1 (mod b)b对于任何一对a和,此数字都是唯一的模b。它的存在只有的最大公约数ab1

维基百科页面的模反元素可以,如果你需要关于主题的更多信息,进行咨询。

输入输出

输入以两个整数或两个整数的列表形式给出。您的程序应输出一个数字,即间隔中的模乘逆0 < c < b,或者一个指示没有逆的值。该值可以是任何值,除了range中的数字之外(0,b),也可以是一个例外。但是,对于没有倒数的情况,该值应该相同。

0 < a < b 可以假设

规则

  • 该程序应在某个时候完成,并应在不到60秒的时间内解决每个测试用例
  • 适用标准漏洞

测试用例

以下测试用例以以下格式提供: 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

计分

这是代码高尔夫,因此每种语言的最短代码胜出。

是类似的问题,但是都要求特定的情况。


6
根据Fermat的Little定理,可以将a的乘法逆(如果存在)作为a ^(phi(b)-1)mod b有效地计算,其中phi是欧拉的上位函数:phi(p0 ^ k0 * p1 ^ k1 * ...)=(p0-1)* p0 ^(k0-1)*(p1-1)* p1 ^(k1-1)* ...不是说它会导致代码较短:)
ngn

1
@Jenny_mathy通常不允许接受其他输入。
Xcoder先生17年

3
我计算了六个似乎是蛮力的答案,不太可能在60秒内运行所有测试用例(其中一些首先给出堆栈或内存错误)。
与Orjan约翰森

1
@ngn:您已将Fermat的小定理(FLT)与Euler的改进混为一谈。Fermat不了解Euler phi函数。此外,仅当gcd(a,b)= 1时,才适用FLT和Euler的改进。最后,以您编写的形式,“ a ^(\ phi(b)-1)mod b”等于1,而不是a ^(-1)。要获得a ^(-1),请使用a ^(\ phi(b)-2)mod b。
埃里克·塔

1
@EricTowers欧拉的结果。关于“ gcd(a,b)= 1”-我确实说过“如果[倒数]存在”。您确定phi(b)-2吗?
ngn

Answers:


11

Mathematica,14个字节

内置 Mathematica必填项:

ModularInverse

这个函数接受两个参数(ab),如果存在则返回mod b的倒数。如果不是,则返回error ModularInverse: a is not invertible modulo b.


7

JavaScript(ES6),79 73 62 61字节

false如果反函数不存在,则返回。

它使用扩展的欧几里得算法,几乎可以立即解决所有测试用例。

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

测试用例


为什么不能像f(c,a,b = 0,d = 1,n = a)=> c那样写函数f的名称?f(a%c,c,d,b-( aa%c)/ c * d,n):a <2 &&(b + n)%n?
RosLuP

@RosLup f(x,y)始终被解析为函数调用,除非它在function关键字之前显式地添加。另一方面,匿名箭头函数则声明为(x,y)=>somethingf=(x,y)=>something并将该函数分配给f变量。
Arnauld

4

果冻,2个字节

æi

在线尝试!

这对模块化逆使用内置函数,对于没有模块化逆则返回0。

果冻,7个字节

R×%⁸’¬T

在线尝试!

在没有模逆的情况下输出空集(表示为空字符串)。对于最大的测试用例,TIO上的内存不足,但是在足够的内存下应该可以工作。

怎么运行的

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.

如果您想使用较大的测试用例,请尝试以下(相对宽松的)版本,该版本需要大量时间而不是内存:

果冻,9个字节

×⁴%³’¬ø1#

在线尝试!

怎么运行的

×⁴%³’¬ø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个字节

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

在线尝试!

递归函数,提供Truefor print f(1,2)(我认为可以接受)和无效输入错误。

我们正在努力寻找xax1(modb)

这可以写成ax1=kb其中k是整数。

服用 moda的这给出1kb(moda)。移动减去给kb1(moda),我们必须求解k

看看它与初始场景的相似之处,让我们通过用f b a a 调用函数来递归求解kf(b%a,a)(之所以有效,是因为Python使用负参数为模数提供了正值)。

程序递归直到a变为1,这仅在原始ab互为质数(即存在一个乘法逆)或以0除以错误而结束时,。

的这个值k可以在方程被取代ax1=kb,得到xkb+1a


3

R + 数字,15字节

numbers::modinv

返回NA那些a没有逆mod的人b

R-Fiddle尝试一下!

R,33个字节(非竞争)

b实际上将失败,因为它实际上会创建一个大小为32*b位的向量。

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

在线尝试!

integer(0)对于a没有逆mod的那些返回(空列表)b


3

Mathematica,18个字节

PowerMod[#,-1,#2]&

输入

[31,73714876143]


3

Python 2中51个 49 54 53 51 49字节

-1字节归功于Officialaimm
-1字节归功于Shaggy

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

在线尝试!

0没有解决方案时打印。


1
输出0a=1b=2; 从测试用例中,应该输出1
毛茸茸的


1
正如Shaggy所指出的,失败是2, 1
Xcoder先生于

@Shaggy现在应该工作了
Rod

这无法在60秒内(在TIO上)为输入返回答案31,73714876143
Ilmari Karonen

3

贾普特9) 8字节

以相反的顺序输入。输出-1不匹配。随着较大的整数变大而逐渐缩小。

Ç*V%UÃb1

测试一下

  • 由于ETH指出了一个错误且非常明显的空间,节省了1个字节。

测试输入73714876143,31似乎在Firefox上产生了内存不足错误(并使Chromium崩溃)。我认为这不是一个有效的答案。
Ilmari Karonen

@IlmariKaronen:我在解决方案中明确指出了这一事实。我们可以假设无限内存用于代码高尔夫,因此内存问题和崩溃不会使该解决方案无效。
毛茸茸的

1
不幸的是,内存问题也使得无法根据挑战的要求在60秒内分辨出您的代码是否能够真正解决测试用例。我怀疑它不会,即使有足够的内存使它不会崩溃,但是如果没有一台能够长时间运行该程序的计算机,也无法确定。
Ilmari Karonen


2

Python 3,49个字节

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

在线尝试!

Python 3,50个字节

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

在线尝试!

IndexError: list index out of range如果没有规则允许的模数乘法逆,则会抛出此错误。


这无法31,73714876143在60秒内(在TIO上)返回输入结果。
Ilmari Karonen

@IlmariKaronen似乎在我的机器上56秒完成(MacBook Pro的'15)
Xcoder先生

2

8th,6字节

invmod

说明

invmod是第八个单词,用于计算a模的逆值b。发生null溢出或其他错误时返回。

用法和测试用例

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个字节

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

在线尝试!

使用欧拉定理。如果倒数不存在,则返回0。

说明

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

Pyth,10个字节

@Jakube节省了3个字节

xm%*szdQQ1

在这里尝试!

返回-1无乘法逆。

代码分解

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.

Pyth15 13字节

KEhfq1%*QTKSK

如果不存在乘法逆,则抛出异常。

在这里尝试!

Pyth,15个字节

Iq1iQKEfq1%*QTK

这增加了很多字节来处理不存在此类数字的情况。如果不需要处理该程序,则可以大大缩短该程序:

fq1%*QTK

在这里尝试!


2个字节保存KExm%*QdKK1
Jakube

或3个字节(如果您交换输入顺序):xm%*szdQQ1
Jakube

@Jakube非常感谢,编辑!
Xcoder先生17年

这是如何运作的?
Kritixi Lithos

@Cowsquack我添加了一个完全原始的代码故障,但是我没有时间包含完整的说明。希望目前已经很清楚了,但是我会尽快添加更完整的解释。
Xcoder先生18年

1

C(gcc),115个字节

#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;}

在线尝试!

扩展的欧几里得算法,递归版本

C(gcc),119字节

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;}

在线尝试!

扩展的欧几里得算法,迭代版


1

C (gcc), 48 110 104 bytes

#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;}

Try it online!

This should work with all inputs (that fit within a long) within 60 seconds.

Edit. I'm already abusing the n variable so I might as well assume that gcc puts the first assignment in %rax.


1
Alas, this gives wrong results even for fairly small inputs due to integer overflow inside the loop. For example, f(3,1000001) returns 717, which is obviously nonsense (the correct answer is 333334). Also, even if this bug was fixed by using a wider integer type, this brute-force approach would certainly time out for some of the larger test cases given in the challenge.
Ilmari Karonen


0

Axiom, 45 bytes

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

0 for error else return z with x*z Mod y =1


0

Python 2, 52 bytes

-3 bytes thanks to Mr. Xcoder.

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

Try it online!

Outputs False on no solution and errors out as b gets larger.

Embedded TIO

I'm just testing out iframes in Stack Snippets and they work absolutely fantastic.


I'm not certain this works, can't i*a%b be 0?
Wheat Wizard

Fails with "maximum recursion depth exceeded" error for input (31,73714876143).
Ilmari Karonen

0

JavaScript (ES6), 42 41 39 38 bytes

Outputs false for no match. Will throw a overflow error as the second number gets to be too large.

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

0

Jelly, 27 bytes

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

Try it online!

Uses Euler's theorem with modular exponentiation. Since Jelly doesn't have a builtin to perform modular exponentiation, it had to be implemented, and it took most of the bytes.


0

Axiom, 99 bytes

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)

it use the function h(); h(a,b) return 0 if error [not exist inverse] otherwise it return the z such that a*z mod b = 1 This would be ok even if arguments are negative...

this would be the general egcd() function that retunr a list of int (so they can be negative too)

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]

this is how use it

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

i find the base algo in internet from https://pastebin.com/A13ybryc

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.