N! modulo m,a ^ p modulo m

时间:2012-01-05 03:34:35

标签: algorithm math

是否有更快的算法来计算(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;
}

3 个答案:

答案 0 :(得分:1)

现在a^n mod mO(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)是二进制(01)和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都是01,所以这些只是告诉您要采用哪些数字。所以你需要的唯一计算是

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

,你应该只使用mod运算符
ans=1
for(int i=1;i<=n;i++) {
    ans *= i;
    if (ans > m) ans %= m;
}

对于第二次计算,使用(p & 1) != 0可能比使用p%2!=0要快得多(除非编译器识别出这种特殊情况并为您完成)。然后,除非必要,否则相同的注释适用于避免%运算符。