什么是快速幂?

什么是快速幂?

我们很多人可能都遇到过一个很简单的问题:如何求出a的n次方?可能很多人的第一反应就是按照以前上学时的方法,将a累乘n次,在程序上就表现为设置一个循环,循环次数设置为n次,在循环体中设置一个中间变量不断累乘a,就如下图这个程序:

在这里插入图片描述

这个程序可能就是我们大多数人下意识的想法,那么,这个程序的性能怎么样呢?我们可以很容易的看出它的时间复杂度是o(n),因此程序的性能会随着n的不断扩大而线性下降,而这就是这个算法的缺陷,那么,该如何降低它的时间复杂度呢?而这就是我们要谈到的快速幂

快速幂的数学原理:

先看普通求幂的数学原理:

2^10=2x2x2x2x2x2x2x2x2x2

可以看到就是一个简单的累乘操作。

接下来看看快速幂是如何对它进行改进的:

2^10=2x2x2x2x2x2x2x2x2x2

2^10=(2x2)x(2x2)x(2x2)x(2x2)x(2x2)

2^10=(2x2) ^5

2^10= 4 ^5

可以看到也是一个简单的累乘操作,但不同之处在于我们改变了底数,使其累乘次数直接少了一半!虽然看着很简单,然而对于程序来说,它的性能却提升了一倍!比如我们原来需要一万次的操作,现在只需要五千次,这个进步不可谓不大!

但是现在我们又面临了一个新问题,如果n是奇数呢?比如上面的10变成了9,这个方法还成立吗?让我们试试。

2^9=2x2x2x2x2x2x2x2x2

2^9=(2x2)x(2x2)x(2x2)x(2x2)x(2)

2^9=(2x2) ^4x(2)

2^9=(4) ^4x(2)

可以看到相比偶次方,奇次方要多乘一个原来的底数,运算次数也比偶次方多一次,不再是原来的一半,然而相比原来的9次,5次仍然还是进步巨大的。

上图我们可以看到,式子中的(4)^4是仍然可以继续重复我们的快速幂操作的,让我们一口气把它做完,直到无法再进行快速幂操作,再来看看最终结果如何。

2^9=2x2x2x2x2x2x2x2x2

2^9=(2x2)x(2x2)x(2x2)x(2x2)x(2)

2^9=(2x2) ^4x(2)

2^9=(4) ^4x(2)

2^9=4x4x4x4x(2)

2^9=(4x4) ^2x(2)

2^9=(16) ^2x(2)

2^9=16x16x(2)

2^9=(256) ^1x(2)

可以看到最终当n降到1时,快速幂操作已经无法进行了,即整个运算过程结束,结果为(256)^1x(2),现在请你先不要往下看,思考一个问题:这两个结果有什么规律呢?这将是我们程序如何实现这个算法的关键。

让我们总结一下整个算法的流程:求a的n次方,若n为偶数,n(幂)=n/2 ,a(底数)乘以自身(2^10=4 ^5);

若n为奇数,n(幂)=(n-1)/2,a(底数)乘以自身,不过整个式子要乘以一个原来的底数(2^9=4 ^4x2)(其实就是代表原来多出来的一次方),若n不为1,重复上面的流程。到这里,其实你可能也明白了,最终结果就是当每一次n为奇数时,我们所保留下来的底数之间的乘积,例如上面例子中,当n=9时,我们保留了2,当n=1时,我们保留了256,最终结果就是256x2。

有了以上认识,整个程序结构其实已经很清晰了,下面就让我们来实现一下这个快速幂算法。

快速幂的算法实现:

如下图:

在这里插入图片描述

在这里插入图片描述

可以看到,相比原来的5次,这个算法只执行了2次便得到了结果,由此可见快速幂算法的优越性,不过当前这个快速幂算法只是比较简单的一种,它还有很多问题需要改进,例如当结果过大,发生溢出怎么办?,又比如其实还可以采用位运算来提高性能,不过由于笔者能力有限,故留给读者自行探索。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值