快速幂

快速幂就是怎么样快速求一个数的幂,一般而言,求幂直接就是连乘,比如a5,ans就是a*a*a*a*a,这样做时间复杂度是O(n)。

而使用快速幂算法可以使时间复杂度降低到O(logn),它是以是数的二进制作为基础,利用二进制的特性进行计算。

举个例子:11的二进制是1011,于是11=23×1+22×01+21×1+20×1,那么a11=a23×1+22×0+21×1+20×1=a23+21+20=a8+2+1=a8*a2*a1

用b表示指数,a表示上面的a,每一步计算时,先判断b的奇偶性,如果是偶数,那么答案ans就乘上a的当前值,每次当b不等于0

进行循环时,a=a*a;随时准备乘上ans,这样a就呈现a1->a2->a4->a8的变化。模拟一下a11的算法:

1.当前b不等于0,(11&1!=0)于是ans*=a(此时ans=a),a=a*a=a2,b除以2,即二进制右移一位,得到二进制b=101。

2.当前b不等于0,(101&1!=0)于是ans*=a2(此时ans=a3),a=a2*a2=a4,b除以2,得到二进制b=10。

3.当前b不等于0,(10&1==0)于是不执行ans*=a4(此时ans=a3),a=a4*a4=a8,b除以2,得到二进制b=1。

4.当前b不等于0,(1&1!=0)于是ans*=a8(此时ans=a11),a=a8*a8=a16,b除以2,得到二进制b=0。

5.当前b等于0,结束。

其他次幂思路相同。

代码如下:

 1 int FastPower(int a,int b)
 2 {
 3     int ans=1;//一定注意赋初值为1
 4     while(b!=0)
 5     {
 6         if(b&1)//其实就是b&1!=0时执行,相当于(b%2!=0),即b为奇数时
 7         {
 8             ans=ans*a;
 9         }
10         a=a*a;
11         b>>=1;//b的二进制右移一位,即b除以2
12     } 
13     return ans;
14 }

入门题目可以看看这个:hdu2035 人见人爱A^B              题解:hdu2035 人见人爱A^B题解

典型题目:

快速幂取模(取余),以51nod1046 A^B mod C为例,

在相应的位置%一个数即可,详见题解:51nod1046 A^BmodC题解

 

快速幂解法还有另外一个思路,就是递归地解决:

假如说有两个数a和b,让你求a的b次方,那么

比如311,可以这样递归地想:

311=3 * 310

310=3* 35

35=3 * 34

34=32 * 32

32=31 * 31

31=3* 30

到头了。。

观察一下,可以分为两种情况:

第一,当b(即指数)为偶数时,ab=ab/2 * ab/2;

第二,当b(即指数)为奇数时,ab=a * ab/2;

递归代码如下:(有点类似二分)

 1 int FastPow(int a,int b)
 2 {
 3     if(b==0)
 4     {
 5         return 1;
 6     }
 7     else if(b&1)//相当于(b%2==1) 
 8     {
 9         return a*FastPow(a,b/2);
10         //return a*FastPow(a,b/2)%c;(如果题目要求求余) 
11     }
12     else
13     {
14         int tmp=FastPow(a,b/2);
15         return tmp*tmp;
16         //return tmp*tmp%c;(如果题目要求求余)
17     }
18 }

题目要求求余的话多传入一个模数c即可,必要时开long long

posted on 2020-04-01 18:06  轻描淡写ぃ  阅读(332)  评论(0编辑  收藏  举报

导航