计算模块化逆


16

给定两个正数x,并nx<2^n写的最短的函数来计算x^-1 mod 2^n。换句话说,找到y这样x*y=1 mod 2^n

您的功能必须至少在合理的时间内完成n=64,因此详尽的搜索将无法进行。

如果倒数不存在,则必须以某种方式向调用者指示(抛出异常,返回标记值等)。

如果您想从哪里开始,请尝试扩展欧几里得算法


在某些数学软件中,这将是一条声明
st0le 2011年

1
@ st0le:是的,在这样的系统中将不允许您使用这样的功能。:-D
克里斯·杰斯特·杨

Answers:


2

Python 95 89

c是你的职责。如果没有倒数(即x为偶数),则返回0。

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

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

这对于偶数x返回0 。它使用Euler定理,并观察到2 ^ n − 1可通过Python内置的快速模幂运算被2 ^(n − 1)− 1 整除。这对于n到7000左右的n来说已经足够快了,它开始花费大约一秒钟以上的时间。


2

Mathematica-22

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

f[x,n]返回yx*y=1 mod 2^n,否则x is not invertible modulo 2^n


2

GolfScript(23个字符)

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

不存在的逆的定点结果为0

这是欧拉定理的简单应用。,所以 X - 1X 2 Ñ - 1 - 1xφ(2n)1(mod2n)x1x2n11(mod2n)

不幸的是,直接计算的指数太大了,因此我们必须使用循环并在循环内进行模块化归约。迭代步骤是,我们有基本情况的选择:要么与x2k1=(x2k11)2×xk=1

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

k=2搭配

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

我正在研究另一种方法,但是哨兵更加困难。

关键的观察是,我们可以通过建立位反了一下:如果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

这给出了19个字符的功能

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

xx&11

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

02n1

01(x+1)n11n

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

ñn x f

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

1

Ruby-88个字符

使用功能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

只是链接的Wiki页面上的递归函数在错误时返回0。


您可以通过内联e:来保存一些字符(e=->a,b{...})[x,2**n][0]。也可以通过测试a%b<1而不是保存字符a%b==0
历史学家2014年


1

Pyth,9个字节

.^Et^2Q^2

在这里尝试!

以相反的顺序输入。或者,也为9个字节:.^EtK^2QK

说明

。^ Et ^ 2Q ^ 2-完整程序。

。^-战俘功能。在Python中也是一样(pow)。
  E-第二个输入。
    ^ 2Q-和2 ^第一个输入。
   t-减少。
       ^ 2-再输入2 ^。

0

GAP,39个字节

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

f(x,n)返回x模的倒数2^n并给出错误信息

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

如果不存在逆。

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.