乘法运算时溢出

Overflow while doing multiplication

本文关键字:溢出 运算      更新时间:2023-10-16

我想计算(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函数find(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);
}

请帮助我查找此代码中的错误。

问题是,如果提供了正确(或错误)的操作数集,则每个操作都会溢出。

另一个代码在评论中暗示,模10^7不会溢出长的(事实上它不会溢出长)

你需要利用的身份

  • (a+b)%c == ((a%c) + (b%c))%c
  • (a*b)%c == ((a%c)*(b%c))%c

这些恒等式的数学证明是微不足道的。

如果值a和b接近long-long所能表示的极限,则将它们相加或相乘可能会溢出。然而,这些恒等式右边的表达式使用模运算符来避免可能溢出的加法或乘法运算。

也不需要使用循环。