幂取模

来源:互联网 发布:嗟乎时运不齐命途多舛 编辑:程序博客网 时间:2024/05/16 15:09

求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)       a^b%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;}

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

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

1 0
原创粉丝点击