Algorithm 计算模为m的3个数的乘积
给定整数a,b,c和m,我需要计算a*b*c%m,其中a,b,c和m可以大到10^18。我知道如何计算a*b%m,如下所示: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; }
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将是无用的。谢谢你的更正。