Algorithm 计算模为m的3个数的乘积

Algorithm 计算模为m的3个数的乘积,algorithm,math,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; }

给定整数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可以这样做吗?

假设函数mulmoda,b,m在返回a*b/m提醒的地方工作。你可以用mulmoda,b,m,c,m来计算a*b*c%m

你可能会问为什么它会起作用?为什么a*b*c%m等于a*b%m*c%m。你可以证明如下:


假设函数mulmoda,b,m在返回a*b/m提醒的地方工作。你可以用mulmoda,b,m,c,m来计算a*b*c%m

你可能会问为什么它会起作用?为什么a*b*c%m等于a*b%m*c%m。你可以证明如下:


模运算的乘法特性如下所示:

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项相乘,然后将结果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

模运算的乘法特性如下所示:

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项相乘,然后将结果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

@invisial会是平等的。你怎么能这么说?@user3086701,我已经添加了解释。@invisial当你移动到第3行=de+r+qm+rq时,我想应该是=dem+dq+erm+rq,我是对的吗?@Gaith,你是对的,因为我没有太多关注它,因为里面的一切都是…*m将是无用的。谢谢你的更正。@invisial会是相等的吗?你怎么能这么说?@user3086701,我已经添加了解释。@invisial当你移到第3行=de+r+qm+rq时,我想应该是=dem+dq+erm+rq,我说得对吗?@Gaith,你说得对,因为我没有太多注意它,因为里面的一切都是…*m将是无用的。谢谢你的更正。