1.1 二进制快速幂
假设有这么一个需求,要求计算出3的100次方,该怎么优化算法,减少运算量?很明显,如果使用动态规划思想,我们知道这里面包含了大量重复运算,根本不需要99次乘法。比如我们可以使用49次乘法算出350,再平方一下,也就是多一次乘法运算,那么就是50次乘法就计算出了结果。
好了,算法思想已经get到了,那么我们就继续想想,如果继续简化,简化到不能简化为止。也许聪明的读者已经想到了。那么就是先一次乘法,平方一下,计算出32,存入数组。然后再计算34,38,316,332,364。然后把100组合一下,100=64+32+4。也就是3100=364*332*34.
总共使用了几次乘法呢?总共使用了8次乘法,计算32,34,38,316,332,364用了5次。计算364*332*34用了3次。这种用少量乘法次数,计算指数的算法被称为二进制快速幂(Binary Exponentiation)。
但是再仔细想想,其实连数组都不需要的。我们这样计算:
p
=
3
2
r
=
1
p
=
3
4
r
=
3
4
p
=
3
8
r
=
3
4
p
=
3
16
r
=
3
4
p
=
3
32
r
=
3
36
p
=
3
64
r
=
3
100
p=3^2\\ r=1\\ p=3^4\\ r=3^4\\ p=3^8\\ r=3^4\\ p=3^{16}\\ r=3^4\\ p=3^{32}\\ r=3^{36}\\ p=3^{64}\\ r=3^{100}\\
p=32r=1p=34r=34p=38r=34p=316r=34p=332r=336p=364r=3100
明白了原理后,代码就非常简单了,以下是python代码:
# _*_ coding:utf-8 _*_
# _*_ coding:utf-8 _*_
def binary_exponentiation(base, power):
power_2 = 1
r = 1
p = base
while power_2 <= power:
if power_2 & power != 0:
r *= p
p = p * p
power_2 = power_2 << 1
return r
if __name__ == '__main__':
print(binary_exponentiation(3, 100))
print(3 ** 100)
print(binary_exponentiation(32, 15))
print(32 ** 15)
测试结果:
515377520732011331036461129765621272702107522001
515377520732011331036461129765621272702107522001
37778931862957161709568
37778931862957161709568
相关文章
- 将一个int类型变量(4字节), 以二进制形式进行输出--showbits.c
- js发送和接收二进制字节流数据
- Java实现 蓝桥杯VIP 算法训练 递归求二进制表示位数
- Centos7二进制部署k8s-v1.20.2 ipvs版本(Prometheus监控k8s)
- Centos7 k8s v1.5.2二进制部署安装-flannel之NAT规则优化
- 算法练习之报数, 最大子序和,最后一个单词的长度,加一,二进制求和
- kubernetes-v1.20.4 二进制部署-rancher-v2.5.1、harbor
- Centos7 k8s v1.5.2二进制部署安装-dashboard--WEB管理
- Centos7 k8s v1.5.2二进制部署安装-服务暴露ingress控制器之traefik
- 使用 ABAP 手动解析包含二进制文件的 multipart/form-data 数据时遇到的问题
- Leetcode 762. 二进制表示中质数个计算置位(可以,一次过)
- 【程序人生】有没有可以快速阅读二进制文本的超人?
- Python: 二进制、八进制、十六进制转换或者输出