从 C++ 中阶乘计算的每次迭代中获取 mod 以防止数字溢出

问题描述

所以,我现在正在学习竞争性编程,主题是“模块化算术”。据说可以用 (a*b) % c = ((a % c) * (b % c)) % c 这本书告诉我可以使用它计算阶乘而不会出现数字溢出。但是在这个例子中,据说你可以像这样对每个操作进行 mod :

long long x = 1;
for (int i = 2; i <= n; i++) {
    x = (x*i) % m; // a mod number of some kind
}
cout << x % m << '\n';

所以,问题是:像 ((x % c) * (i % c)) % c 这样使用不是更好吗?所以我们不会冒“i”数字溢出的风险?

解决方法

((x % c) * (i % c)) % c 一样使用它不是更好吗?

在示例中,m 的值是否适合 32 位整数?

如果为真,xi 的值也是 32 位的,这意味着只有一次乘法不会溢出,因为 x 可以包含 64 位整数。所以是安全的。

如果不是,即使我们用 ((x % m * (i % m)) % m 替换计算,它仍然可能溢出,因为 x % m 可能大于 32 位整数。所以我不认为是这样。

所以两种方式都有效。而且您的方式不会改变算法的时间复杂度。然而它没有任何优势,只是更多的计算和更多的输入:)


我想再提一个:

这本书告诉我可以使用它计算阶乘而不会出现数字溢出。

不,我们可以用这种方式计算阶乘模 m。 在竞争性编程中,大多数问题都避免了通过这种方式答案变得太大的问题。所以我们总是可以在恒定时间(没有大整数)计算算术运算。