我想计算(N * N *(N + 1)/ 2)mod M的值,其中该N可以达到10 ^ 18并且M最大可达10 ^ 7。我试着编码它,但不知道为什么它溢出的原因。这是我的代码:
主要是我做这样的事情:
long long tt=mulmod(N,N+1,MOD)*InverseEuler(2,MOD);
long long mm=mulmod(tt,N,MOD);
并且mulmod函数找到(A * B)%C。如下:
long long mulmod(long long a,long long b,long long c)
{
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;
}
反向欧拉也是这样的:
long long p(long long n,int m,long long int MOD)
{
if(m == 0) return 1%MOD;
long long x = p(n,m/2,MOD);
if(m%2 == 0)
return (x*x)%MOD;
else
return (((x*x)%MOD)*n)%MOD;
}
long long InverseEuler(int n,int MOD)
{
return p(n,MOD-2,MOD);
}
请帮助我找到此代码中的错误。
答案 0 :(得分:0)
问题是,如果提供了正确(或错误)的一组操作数,每个操作都会溢出。
justanothercode在评论中暗示模数10 ^ 7不会长时间溢出(实际上它不会溢出很长时间)
您需要使用
的身份(a+b)%c == ((a%c) + (b%c))%c
(a*b)%c == ((a%c)*(b%c))%c
这些身份的数学证明是微不足道的。
当值a和b接近long long可以表示的极限时,添加或乘以它们会溢出。但是,这些标识右侧的表达式使用模运算符来避免可能溢出的加法或乘法。
也不需要使用循环。