c ++中大数字的模乘

Pra*_*akh 6 c++ algorithm multiplication modular

我有三个整数A,B(小于10 ^ 12)和C(小于10 ^ 15).我想计算(A*B)%C.我知道

(A * B) % C = ((A % C) * (B % C)) % C
Run Code Online (Sandbox Code Playgroud)

但是如果A = B = 10 ^ 11,那么上面的表达式将导致整数溢出.对于上述情况是否有任何简单的解决方案,或者我必须使用快速乘法算法.

如果我必须使用快速乘法算法,那么我应该使用哪种算法.

编辑:我在C++中尝试过上述问题(不会导致溢出,不确定原因),但答案应该是吗?

提前致谢.

Bat*_*eba 14

您可以使用Schrage的方法解决此问题.这允许您将两个有符号数相乘,a并且z两者都具有一定的模数,m而不会生成大于该数的中间数.

它基于模数的近似因子分解m,

m = aq + r 
Run Code Online (Sandbox Code Playgroud)

q = [m / a]
Run Code Online (Sandbox Code Playgroud)

r = m mod a
Run Code Online (Sandbox Code Playgroud)

where []表示整数部分.如果r < q0 < z < m ? 1,则两个a(z mod q)r[z / q]横亘在范围0,...,m ? 1

az mod m = a(z mod q) ? r[z / q]
Run Code Online (Sandbox Code Playgroud)

如果这是否定的则添加m.

[该技术经常用于线性同余随机数发生器].

  • 此外,您可以将其用作递归算法以包含所有`r> = q`.对产品`r*[z/q]`重复上述算法,所以新值变为:`a2 = r``z2 = [r/q]`这保证了`a`值减小:`a> r = a2` - >`a2 <a`最后,当`a <= sqrt(m)`时,则:`a*a <= m` - >`q> = a> r` - >`r <q `并且算法终止. (3认同)

hig*_*aro 5

鉴于您的公式和以下变化:

(A + B) mod C = ((A mod C) + (B mod C)) mod C 
Run Code Online (Sandbox Code Playgroud)

您可以使用分而治之的方法来开发既简单又快速的算法:

#include <iostream>

long bigMod(long  a, long  b, long c) {
    if (a == 0 || b == 0) {
        return 0;
    }
    if (a == 1) {
        return b;
    }
    if (b == 1) {
        return a;
    } 

    // Returns: (a * b/2) mod c
    long a2 = bigMod(a, b / 2, c);

    // Even factor
    if ((b & 1) == 0) {
        // [((a * b/2) mod c) + ((a * b/2) mod c)] mod c
        return (a2 + a2) % c;
    } else {
        // Odd exponent
        // [(a mod c) + ((a * b/2) mod c) + ((a * b/2) mod c)] mod c
        return ((a % c) + (a2 + a2)) % c;
    }
}

int main() { 
    // Use the min(a, b) as the second parameter
    // This prints: 27
    std::cout << bigMod(64545, 58971, 144) << std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这是 O(log N)