计算3个数模m的乘积

时间:2014-01-05 06:11:39

标签: algorithm math

给定整数a,b,c和m,我需要计算(a*b*c)%m,其中a,b,c和m可以大到10 ^ 18。我知道如何计算(a * b)%m如下:

unsigned long long mulmod(unsigned long long a,unsigned long long b,unsigned long long c){
unsigned long long x = 0,y=a%c;
while(b > 0){
    if(b%2 == 1) {
        x = (x+y)%c;
    }
    y = (y*2)%c;
    b /= 2;
}
return x%c;

}

可以为(a*b*c)%m完成这样的事情吗?

2 个答案:

答案 0 :(得分:3)

假设您的函数mulmod(a, b, m)在返回(a * b) / m提醒的位置工作。您可以按(a * b * c) % m

计算mulmod(mulmod(a, b, m), c, m)

你可能为什么这样做?为什么(a * b * c) % m等于((a * b) % m) * c % m。您可以证明如下:

Let          a * b = dm + r
             c     = em + q
Therefore,   a * b * c = (dm + r) * (em + q)
                       = (dem + dq + er)m + rq

So           (a * b * c) % m = [(de + r + q)m + rq] % m 
                             = rq % m

How about    [(a * b) % m] * c % m
We know that (a * b) % m = r
Therefore    [(a * b) % m] * c % m = [r * (em + q)] % m
                                   = (rem + rq) % m
                                   = rq % m

Hence, [(a * b) % m] * c % m and (a * b * c) % m are the same

答案 1 :(得分:1)

模运算的乘法属性如下:

ab mod m = (a mod m)(b mod m) mod m                          // Rule 1

由此得出:

abc mod m = (ab mod m)(c mod m) mod m                       // Expand (ab)c mod m
          = ((a mod m)(b mod m) mod m mod m)(c mod m) mod m // Expand ab mod m
          = ((a mod m)(b mod m) mod m)(c mod m) mod m       // Trim extra mod m
          = (a mod m)(b mod m)(c mod m) mod m               // Reverse rule 1 with
                                                            // a' = (a mod m)(b mod m)
                                                            // b' = c mod m

这表明实现三向模乘的两个选项。最简单的是将所有三个mod m项相乘,并对结果进行修改,但如果修改每个中间结果,则不太可能遇到溢出。假设C ++:

template <typename T, size_t N>
T mulmod(T (&multiplicands)[N], T m) {
    T result = 1;
    for (T n : multiplicands)
        result = (result * (n % m)) % m;
    return result;
}

int nums = {123, 345, 656, 841};
std::cout << mulmod(nums, 373) << "\n"; // Prints 88