我在Python中有这个程序:
# ...
print 2 ** (int(input())-1) % 1000000007
问题是这个程序在大数字上运行了很长时间。我用C ++重写了我的代码,但有时我得错了答案。例如,在数字12345678
的Python代码中,我有749037894
并且它是正确的,但在C ++中我有-291172004
。
这是C ++代码:
#include <iostream>
#include <cmath>
using namespace std;
const int MOD = 1e9 + 7;
int main() {
// ...
long long x;
cin >> x;
long long a =pow(2, (x-1));
cout << a % MOD;
}
答案 0 :(得分:2)
如前所述,您的问题是对于大指数,您有整数溢出。
为了克服这一点,请记住模块化乘法具有以下特性:
(A * B)mod C =(A mod C * B mod C)mod C
然后你可以使用快速求幂方案实现'e to power p modulo m'功能。 假设没有负面力量:
long long powmod(long long e, long long p, long long m){
if (p == 0){
return 1;
}
long long a = 1;
while (p > 1){
if (p % 2 == 0){
e = (e * e) % m;
p /= 2;
} else{
a = (a * e) % m;
e = (e * e) % m;
p = (p - 1) / 2;
}
}
return (a * e) % m;
}
请注意,在每次乘法后都会进行余数处理,因此如果单次乘法不会溢出,则不会发生溢出(1000000007
的{{1}}和m
都是如此。< / p>
答案 1 :(得分:0)
您似乎正在处理正数,而且这些数字超出了您为其存储分配的位数。还要记住,Python和C / C ++之间的区别在于计算负值的模数。要获得类似的计算,您需要将模数添加到值中,以便在采用模数之前它是正面的,这是它在Python中的工作方式:
cout << (a+MOD) % MOD;
在获取模数之前,您可能需要添加MOD n次,直到临时值为正。
答案 2 :(得分:0)
许多其他答案都提到过,你的问题在于整数溢出。
你可以像deniss建议的那样做,并实现你自己的modmul()和modpow()函数。
但是,如果这是一个项目的一部分,需要进行大量的大量计算,我建议使用一个&#34;大数字库&#34;例如GNU GMP或mbedTLS Bignum library。
答案 3 :(得分:0)
在C ++中,各种基本类型都有固定的大小。例如,long long
通常为64位宽。但宽度因系统类型和其他因素而异。如上所述,您可以查看climits.h以了解您的特定环境的限制。
将2增加到12345677的功率将涉及将二进制数10
向左移位12345676位,这将不适合64位long long
(我怀疑不太适合long long
实施)。
要考虑的另一个因素是pow
会返回double
(或long double
)depending on the overload used。您没有说出您正在使用的编译器,但是当调用pow
的结果被分配给long long
变量a
时,您很可能会收到有关可能的截断或数据丢失的警告
最后,即使pow
返回一个long double,我怀疑指数12345677太大而无法存储在long double
中,因此pow
可能会返回正无穷大,然后被截断一些适合long long
的位模式。您当然可以通过引入中间long double
变量来检查它,以接收pow
的值,然后您可以在调试器中检查它。