如何避免快速模幂运算中的溢出

时间:2013-07-29 10:00:57

标签: c c99 integer-overflow

我正在尝试解决SPOJ上需要模幂运算的问题。我使用以下C代码

long long modpow(long long a,long long b,long long mod)
{
    long long product,pseq;
    product=1
    pseq=a%mod;
    while(b>0)
    {
        if(b&1)
            product=(product*pseq)%mod;
        pseq=(pseq*pseq)%mod;
        b>>=1
    }
    return product;
}

问题是,当我想要计算(2^249999999997)%999999999989时,由于溢出,它会给出答案0。我怎样才能避免溢出?

3 个答案:

答案 0 :(得分:4)

Untestet,但你明白了。只要2*mod小于最大可表示long long值且abmod为正值,这就应该有效。

long long modpow(long long a,long long b,long long mod)
{
    long long product,pseq;
    product=1;
    pseq=a%mod;
    while(b>0)
    {
        if(b&1)
            product=modmult(product,pseq,mod);
        pseq=modmult(pseq,pseq,mod);
        b>>=1;
    }
    return product;
}

long long modmult(long long a,long long b,long long mod)
{
    if (a == 0 || b < mod / a)
        return (a*b)%mod;
    long long sum;
    sum = 0;
    while(b>0)
    {
        if(b&1)
            sum = (sum + a) % mod;
        a = (2*a) % mod;
        b>>=1;
    }
    return sum;
}

答案 1 :(得分:0)

另外一个建议是利用999999999989是素数的事实。 通过使用关系,(a ^ n)= a%n(其中n是素数),你可以简化操作。

答案 2 :(得分:-1)

你可以使用 unsigned long long 而不是 long long ,它可以帮助你玩更高的值,范围是0到18,446,744,073,709,551,615。