袁家伟

导航

快速幂算法 ——递归与迭代

快速幂算法讲解

递归算法:

int cpow(int m,int n)
{
    if(n==0) return 1;
    else if(n%2==1){
        return cpow(m,n-1)*m;
    }else if(n%2==0)
    {
        int temp = cpow(m,n/2);
        return temp*temp;
    }
}

例如:当我们已知了 2^3,那么在计算2^6不就是相当于2^3*2^3,而快速幂就是运用了这样的原理,但是,如果我们碰到的幂为奇数时怎么办?直接提出来一个幂不就好了,例如在计算2^7,将此转换成2*2^6,之后2^6继续运用上面对待偶数的办法不就好了;

总结以上啰里啰嗦的话,转换成公式就是一下:

1)当b是奇数时,那么有 a^b = a * a^*(b-1)

2)当b是偶数时,那么有 a^b = a^(b/2) * a^(b/2)

迭代算法:

int qpow(int a,int n)
{
    int nas = 1;
    while(n){
        if(n&1)
            ans *= a;
        a *= a;
        n>>=1;
    }
    return ans;
}

迭代算法运用到了位运算&,将递归算法的(n%2==0)改为(n&1);

对于 a ^ b来说,若果把 b 写成2 进制,那么b 就可以写成若干二次幂之和,如13 的二进制 1101,于是3 号位 、2号位、0号位就都是1,那么就可以得到13 = 2^3 + 2^2 + 2^1 = 8 + 4 + 1。所以a ^13 = a^8 * a^4 * a^1。

通过同样的推导,我们可以把任意的a^b 表示成 a^(2^k)……、a^8、a^4、a^2、a^1中若干的乘积。若果二进制的i号位为1.那么想中的a^(2^i)就被选中。于是可以得到计算a^b的大致思路:令i 从0到k枚举b的二进制的每一位,如果为1 那就累计a^(2^i)。注意

a^(2^k)……、a^8、a^4、a^2、a^1前一项总是等于后一项的平方。具体步骤。

(1)初始令ans = 1,用来存放累积的结果。

(2)判断b的二进制末尾是否为1 ,(及判断 b&1 是否为 1),也可以理解为判断b 是否为奇数。如果是的话,令ans乘上a的值。

(3)令a平方,并使b右移一位,(也可以理解为,b/2)

(4)只要b 大于0,就返回(2)。

以上;

 

posted on 2020-02-17 22:52  袁家伟  阅读(488)  评论(0编辑  收藏  举报