我搜索了这个问题的答案,我得到了各种有用的链接但是当我实现这个想法时,我得到了错误的答案。
这就是我所理解的:
如果m是素数,则非常简单。任何数字'a'的逆模数可以计算为:inverse_mod(a) = (a^(m-2))%m
但是当m不是素数时,我们必须找到m的素因子,
即m= (p1^a1)*(p2^a2)*....*(pk^ak).
这里p1,p2,....,pk是m的主要因子,a1,a2,....,ak是它们各自的权力。
然后我们必须计算:
m1 = a%(p1^a1),
m2 = a%(p2^a2),
.......
mk = a%(pk^ak)
然后我们必须使用中国剩余定理(https://en.wikipedia.org/wiki/Chinese_remainder_theorem)
组合所有这些余数我实现了m = 1000,000,000的这个想法,但我仍然得到了错误的答案。
这是我对m = 1000,000,000的解释,这不是素数
m= (2^9)*(5^9)
其中2和5是m的主要因素。
设a是必须计算逆模m的数字。
m1 = a%(2^9) = a^512
m2 = a%(5^9) = a^1953125
Our answer will be = m1*e1 + m2*e2
where e1= { 1 (mod 512)
0 (mod 1953125)
}
and e2= { 1 (mod 1953125)
0 (mod 512)
}
现在计算'e1'和'e2',我使用扩展欧几里德算法。 https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm
守则是:
void extend_euclid(lld a,lld b,lld& x,lld& y)
{
if(a%b==0)
{
x=0;
y=1;
return ;
}
extend_euclid(b,a%b,x,y);
int tmp=x;
x=y;
y=tmp-(a/b)*y;
}
Now e1= 1953125*y and e2=512*y;
So, Our final answer will be = m1*e1 + m2*e2 .
但是在完成所有这些之后,我得到了错误的回答。
请解释并指出我在理解中国剩余定理时所犯的任何错误。
非常感谢。
答案 0 :(得分:2)
如果a
和m
为coprime,a
模m
的倒数仅存在。如果它们不是互质的,那么没有什么能帮到你。例如:2
mod 4
的反转是什么?
2*0 = 0 mod 4
2*1 = 2 mod 4
2*2 = 0 mod 4
2*3 = 2 mod 4
所以没有反过来。
这确实可以通过使用扩展的欧几里德算法来计算(虽然我不确定你是否做得对),但在我看来,最简单的方法是使用{{3} }:
a^phi(m) = 1 (mod m)
a*a^(phi(m) - 1) = 1 (mod m)
=> a^(phi(m) - 1) is the invers of a (mod m)
其中phi
是Euler's theorem:
phi(x) = x * (1 - 1/f1)(1 - 1/f2)...(1 - 1/fk)
where fi > 1 is a divisor of x (not necessarily a prime divisor)
phi(36) = 36(1 - 1/2)(1 - 1/3)(1 - 1/4)(1 - 1/6)(1 - 1/9)(1 - 1/12)(1 - 1/18)(1 - 1/36)
因此可以在O(sqrt n)
中计算出来。
然后可以使用totient function计算取幂。
如果您想了解如何使用扩展的欧几里德算法更快地找到逆,请阅读exponentiation by squaring。我不认为中国剩余定理可以在这里提供帮助。
答案 1 :(得分:0)
如果你想为p prime计算^( - 1)mod p ^ k,首先计算一个^( - 1)mod p。给定一个x,使得ax = 1(mod p ^(k-1)),你可以“Hensel lift”---你正在寻找0和p-1之间的y,这样a(x + yp ^( k-1))= 1(mod p ^ k)。做一些代数,你会发现你正在寻找y,使得y p ^(k-1)= 1 - ax(mod p ^ k)---即。 a y =(1-ax)/ p ^(k-1)(mod p),其中除以p ^(k-1)是精确的。您可以使用(mod p)的模块化逆转来解决这个问题。
(或者,只需注意一个^(p ^(k-1)(p-1) - 1)= 1(mod p ^ k)。我提到Hensel提升,因为它的工作原理更为普遍。)< / p>
答案 2 :(得分:0)
我相信以下功能会做你想要的。如果合适,请从long
更改为int
。如果没有反转则返回-1,否则返回[0..m)
范围内的正数。
public static long inverse(long a, long m) { // mult. inverse of a mod m
long r = m;
long nr = a;
long t = 0;
long nt = 1;
long tmp;
while (nr != 0) {
long q = r/nr;
tmp = nt; nt = t - q*nt; t = tmp;
tmp = nr; nr = r - q*nr; r = tmp;
}
if (r > 1) return -1; // no inverse
if (t < 0) t += m;
return t;
}
我不能按照你的算法来确切地看到它有什么问题,但我有一些一般性评论:Euler的totient函数通常计算起来相当慢,这取决于它在主要因素分析上的作用。中国剩余定理在许多情况下用于组合结果mod互质是有用的,但是这里并不是必须使这个特定问题过于复杂,因为你最终必须考虑你的模数,这是一个非常慢的操作。并且在循环中实现GCD和模块化逆转更快,而不是使用递归,尽管这两种方法当然同样有效。