首页 > 代码库 > 幂取模

幂取模

求a^b%c的结果,

方法一:

    a*b%c = ((a%c)*b)%c;

代码如下:

int work(int a, int b, int c)
{
    int res = 1;
    for (int i = 0; i < b; i ++) {
        res = res * a % c;
    }
    return res;
}

但是这种方法复杂度太高,不适合大数据运算,下面介绍一种更快的方法。

方法二:

b可以表示成二进制的形式,我们用p数组表示相应位权的权值,用2的指数次方表示位权,则

b = p[i]*2^i + p[i-1]*2^(i-1) + p[i-2]*2^(i-2) + ... + p[1]*2^1 + p[0]*2^0

我们知道相邻位置,高位权是低位权的2倍,所以在p[i] === 1的情况下,相邻两位高位是低位的两倍。

a^b = a^( p[i]*2^i + p[i-1]*2^(i-1) + p[i-2]*2^(i-2) + ... + p[1]*2^1 + p[0]*2^0 )

      = a^( p[i]*2^i ) * ( a^( p[i-1]*2^(i-1) ) ) * ( a^( p[i-2]*2^( i-2 ) ) )*...*( a^( p[1]*2^1 ) ) * (a^(p[0]*2^0))


有上我们知道表达式相邻两位在p[i] === 1的情况下,高位是低位的平方。

即:a^( p[i]*2^i ) =  ( a^( p[i-1]*2^(i-1) ) ) * ( a^( p[i-1]*2^(i-1) ) ) ;

又有上面的表达式我们知道,当p[i] = 0时,a^( p[i]*2^i ) = a ^ 0 = 1;

所以我们只要p[i] = 1的时候,表达式乘以a^( p[i]*2^i )


我们得到下面的代码:


int mod_exp(int a, int b, int c)        //¿ìËÙÃÝÈ¡Óàa^b%c
{
    int res, t;
    res = 1 % c;
    t = a % c;
    while (b)
    {
        if (b & 1)
        {
            res = res * t % c;
        }
        t = t * t % c;
        b >>= 1;
    }
    return res;
}

因为我们只需要判断相应位置是否为1,我们可以知道二进制数的2^0位的权值为1,则这个是一定是奇数,所以我们可以得到下面的代码:


int mod_exp(int a, int b, int c)       
{
    int res, t;
    res = 1 % c;
    t = a % c;
    while (b)
    {
        if (b % 2)
        {
            res = res * t % c;
        }
        t = t * t % c;
        b /= 2;
    }
    return res;
}

这个代码易于理解,但是效率略差于上面的代码(其实也没差多少)。

注:位运算是运算器的基本操作,不需要调用累加器,而乘除是比较复杂的,基于加法运算,需要调用累加器!

幂取模