快速幂的算法理解

来源:互联网 发布:php 字节数组转字符串 编辑:程序博客网 时间:2024/05/16 08:32

一直听说过快速幂,一直没有用过。这下稍微有了点空闲时间,做个笔记自己看看。。

求一个数的n次幂常见的是n次循环。例如。

  double Power(double base,int exponent){bool flag=false;   double total=1;   if(exponent<0){    flag=true;   exponent=-exponent;   }   while(exponent--) {total=total*base;}return flag?1/total:total;}
复杂度是O(n)。

快速幂算法是怎样的?

比如求5^13次方,分析如下:

①、13=1101(二进制形式)

②、1101

        2^3*1+ 2^2*1 +2^1*0 + 2^0*1

        设算式为  A=5^(2^3),B=5^(2^2),C=5^(2^1),D= 5^(2^0)

对应的位依次为 1             1                0                1

        化简       

        5^13=A   * B  * D

       可以看到如果对应二进制位为1.则其代表的算式会出现。并且D*D=C,C*C=B,B*B=A。

       计算便可以这样来看。

     一开始是D,判断D所属未位置为1,乘上D。D-->C

     判断C所属位置为0,不乘C,C-->B。

     判断B所属位置为1,乘B,B-->A。

     判断A所属位置为1,乘A,结束。

        该性质具有一般性。因为整数都可以拆分成二进制表示。

       设base=D,ans=1。

       从右到左依次从1101取值。如果为1,则ans*=base,否则不做变化。每轮更新base,由上面的性质知道base=base*base.则可以向上更新。

       到此,所有困惑都明白了。得到如下代码。

class Solution {public:   double Power(double base,int exponent)//底数作为一开始的D{bool flag=false;   double total=1;   if(exponent<0){    flag=true;   exponent=-exponent;   }   while(exponent)  {  if(exponent&1)//如果存在1,则乘上该值  {     total*=base;}exponent>>=1;  base=base*base;//更新底数    }return flag?1/total:total;}};