是否有更快的算法来计算(n!modulo m)。 比每个乘法步骤的减少更快。 并且 是否有更快的算法来计算(a ^ p modulo m)比右 - 左二进制方法更好。
这是我的代码: N! mod m
ans=1
for(int i=1;i<=n;i++)
ans=(ans*i)%m;
a ^ p mod m
result=1;
while(p>0){
if(p%2!=0)
result=(result*a)%m;
p=(p>>1);
a=(a*a)%m;
}
答案 0 :(得分:1)
现在a^n mod m
是O(logn)
,这是Modular Exponentiation算法。
现在对于另一个n! mod m
,您提出的算法显然是O(n)
,所以显然第一个算法更快。
答案 1 :(得分:1)
计算a^p modulo m
的标准技巧是使用连续的平方。我们的想法是将p
扩展为二进制,比如说
p = e0 * 2^0 + e1 * 2^1 + ... + en * 2^n
其中(e0,e1,...,en)
是二进制(0
或1
)和en = 1
。然后使用指数定律来获得a^p
a^p = a^( e0 * 2^0 + e1 * 2^1 + ... + en * 2^n )
= a^(e0 * 2^0) * a^(e1 * 2^1) * ... * a^(en * 2^n)
= (a^(2^0))^e0 * (a^(2^1))^e1 * ... * (a^(2^n))^en
请注意,每个ei
都是0
或1
,所以这些只是告诉您要采用哪些数字。所以你需要的唯一计算是
a, a^2, a^4, a^8, ..., a^(2^n)
您可以通过平方前一个术语来生成此序列。由于您要计算答案mod m
,因此应首先进行模运算。这意味着您要计算以下内容
A0 = a mod m
Ai = (Ai)^2 mod m for i>1
答案是
a^p mod m = A0^e0 + A1^e1 + ... + An^en
因此,计算需要log(p)
个方格并调用mod m
。
我不确定是否存在阶乘的模拟,但是开始寻找的好地方是Wilson's Theorem。此外,您应该对m <= n
进行测试,在这种情况下n! mod m = 0
。
答案 2 :(得分:0)
对于第一次计算,如果ans > m
:
ans=1
for(int i=1;i<=n;i++) {
ans *= i;
if (ans > m) ans %= m;
}
对于第二次计算,使用(p & 1) != 0
可能比使用p%2!=0
要快得多(除非编译器识别出这种特殊情况并为您完成)。然后,除非必要,否则相同的注释适用于避免%
运算符。