[记录]关于个人理解的快速幂的非递归算法

代码难免会有错误,还请见谅,同时也欢迎各位指出错误,我也会及时进行修改更正,谢谢。

在刷题过程中经常会见到类似a^b或者a^b%c的题目,往往题目范围给出的数进行n次乘法后,往往会超出范围,因此,一种更加简单,时间复杂度更出色的算法能够更快的得出结果。

首先,还是给出最简单的循环相乘,以方便比较。

1):

但如果对于时间没有要求,仅仅需要将正确结果输出的话,我们可以通过创建一个数组来进行对结果的存储,类似于大数阶乘中存储结果的方法,代码如下:

容易理解,a^b即通过b此循环,使b个a相乘,得到结果,这种方法只有在a ,b的值不是太大时适用,如果b的值达到10的7 次方,8次方甚至更大时,时间复杂度为O(n)的算法显然不能满足要求。

而快速幂的时间复杂度只有O(log n),显然比上面的方法快了非常多,我们从 2^11次方来理解这个算法,在开始之前,我们要熟悉一个位移运算符中的右移运算符 >>和位运算符 &。

显然, 这两个运算符都是作用于的 。

举个例子 ,13的二进制是1101。

右移运算符 >>

int 型,32位操作系统下,占32个bits,则表示为0000 0000 0000 0000 0000 0000 0000 1101,  如果是11>>1,即向右移动一位,相当于除以2,(2进制可以由十进制不断除以2得到的余数倒序写出)

>>不改变数的原值,如

int c=11;

int d=c>>1;

cout<<d;

cout<<c/2;

得到的结果是 5   5

>>= 改变数的值 

如int c=11;

int d=c>>=1;

cout<<d;

cout<<c/2;

得到的结果是 5   2

1101的第四个1 丢弃 ,变为110,首位空出位置 补0(13是正数),表示为 0000 0000 0000 0000 0000 0000 0000 0110,即5,在非负数范围,a>>1于a/2相同。

位运算符&

按位与运算符"&" 的功能是当二进位均为1时,输出才为1 ,否则为0。

了解了这些,接下来我们就开始对快速幂的解释。

先上代码:

假设我们要计算2 的13次方(当然这个数不算大,这个例子只是为了解释方便)

13可以表示为二进制的1101,即a1(1*2^3)+a2(1*2^2)+a3(0*2^1)+a4(1*2^0);

2^13=a1*a2*a3*a4;

此时看起来只有4次乘法运算,但a1 a2 a3 a4都需要进行更多次的乘法运算,而我们又知道

a^1 * a^1 =a^2;

a^2 * a^2 =a^4;

 a^4 * a^4=a^8;

1101又可以拆成1000+100+00+1(二进制表示)

也就是2^1000  *2^100 * 2^00 * 2*1; 

表示成十进制--->2^8 *2^4 * 2^1 = 2^13;

我们知道 任何数的0次幂都为1(0的0次方不讨论),因此,当某一位为0时,不进行累乘.

首先 int ans =1;用来存储结果

a表示底数,b表示幂

从第一层循环开始解释:

一:

while (b>0)

a的b次方 b大于0时 进行下列循环, 

问:为什么输入了b不为0,最后还会停止循环?

注意看 第14行b进行了 b>>=1的位运算,如果最后b的每一位有意义的数(剩下的都是0)都乘到了ans上,由于不断补0,剩下32位0,while循环自然终止。

二:

if(b&1)

这一步用来判断二进制数的末尾是0还是1,前面讲过,只有两位均为1时,才为真值,即最后一位不为0,乘法有意义(乘数不为1),让ans=ans*a;

a*=a;

上面说过:

2^11 表示成十进制--->2^8 *2^2 * 2^1 = 2^11;

2^2=2^1*2^1;

2^4=2^2*2^2;

2^8=2^4*2^4;

因此,a的自乘可以使2^8的8次方的运算转为2^4的平方运算,可以减少进行乘法运算的次数,

注意:a*=a;无论if(b&1)是否成立都会执行

四:

b>>=1

b=1101 , ans=1;a=2^2;

b向右移动一位,即1101经过上述过程后,b=110

为了更好理解该过程,图:

 注意:ans=ans*a是先于a的自乘进行的。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值