快速幂

废话不多说, 直接步入正题。

现在oj网站的题或者竞赛的题,如果a的b次幂且b很大,那么题中大多会让你把结果对一个数取余也就是求模,例如a^b%c这种,当然如果是考高精度的题除外。

接下来我将提供一种常规算法和两种竞赛中主流的快幂算法。

首先我们设题目要求为a^b mod c

常规算法

这里我就不多作解释,直接码代码了

[cpp]  view plain  copy
  1. int mod(int a, int b, int c){  
  2.     int i, ans = 1;  
  3.     for (i = 0; i < b; i++)  
  4.         ans = (ans * a) % c;    //在这里对c取余是为了防止数据溢出  
  5.     return ans;  
  6. }  

这个算法的时间复杂度为O(n),不是很高,但是一旦题目中b的取值很大且时间要求高的话,那么这个时间复杂度就危险了,接下来得靠我们的快幂算法来摆平

快幂算法1

这里我们需要两个公式:

这两个公式都不难理解,自己可以验证一下,3^4 = 9^2。

有了这两个公式之后我们就可以考虑思路了。

我们就以b为偶数来举例。

a^b%c = ((a^2)^b/2)%c;

在这里我们假设b/2还是偶数,那么

((a^2)^b/2)%c = (((a^2)^2)^(b/2)/2)%c;到这里就可以了.

我相信稍微懂点算法的人都可以看出来这是一个递归的过程,如果不理解那么自己再找几个数试一试

理解之后就可以看这个快幂的代码了

[cpp]  view plain  copy
  1. int quickMod(int a, int b, int c)  
  2. {  
  3.     int ans = 1;  
  4.     while (b)  
  5.     {  
  6.   
  7.         if (b % 2 == 1)  
  8.             ans = (ans * a) % c;  
  9.         b /= 2;  
  10.         a = (a * a) % c;  
  11.     }  
  12.     return ans;  
  13. }  

这个算法的时间复杂度为O(logn),对于大多数oj网站或者竞赛题相信都可以AC过去。


快幂算法2

我们先将b按2进制展开假设b = 10, 那么b的二进制为1010,也就是0*2^0+1*2^1+0*2^2+1*2^3 = 10;

所以 a^b = a^(0*2^0+1*2^1+0*2^2+1*2^3 ) = a^(2^1) * a(2^3);这种简单的转换在初中就学过了吧,相信大家都懂

所以a^b%c = a^(2^1) * a(2^3) % c =( a^(2^1) % c) * (a(2^3)%c)%c;

讲到这里就可以写代码了

[cpp]  view plain  copy
  1. int quickMod(int a, int b, int n)  
  2. {  
  3.     int ans = 1;  
  4.     while (b)  
  5.     {    
  6.         if (b & 1) //如果二进制位为1  
  7.             ans = ans * a % n;  
  8.         a = a * a % n;  
  9.         b >>= 1;   //b向右移1位  
  10.     }  
  11.     return ans;  
  12. }  

写到这里就差不多该结束了,相信有心的读者可以发现这两种快幂思想的核心都是二分法,所以时间复杂度都为 O(logn)。

虽然推倒过程完全不一样,但是到代码实现这个层面几乎是一模一样的,if(b % 2 == 1) 就相当于if(b & 0x1), b /= 2也就是b>>=1。所以算法是多么优美又多么奇妙,希望大家可以在算法之路上不断前行,继续努力!

转载  https://blog.csdn.net/u013174702/article/details/43761197


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值