小白算法-快速幂
快速幂,二进制取幂(Binary Exponentiation,也称平方法),是一个在 O(logn)的时间内计算 (a^n) 的小技巧,而暴力的计算需要 的时间。而这个技巧也常常用在非计算的场景,因为它可以应用在任何具有结合律的运算中。其中显然的是它可以应用于模意义下取幂、矩阵幂等运算,我们接下来会讨论。
算法描述
计算a的n次方表示n个a乘在一起:a^n = a * a * a ...*a,然而当a,n太大的时候,这种方法就不太是不太适用了,我们将取幂的任务按照指数的二进制表示 来分割成更小的任务
首先我们将n表示为2进制,举个例子:
3 ^ 13 = 3(1101)2 = 3 ^ 8 * 3 ^ 4 * 3 ^ 1
因为n有[log2 n] + 1 个二进制位,因此我们知道了a^1,a^2,a^4,a^8...... a^ 2[log2 n]后,我们只要计算O(log n)次乘法就可以计算出a^n
于是我们只需要知道一个快速的方法来计算上述3的2^k次幂的序列。这个问题很简单,因为序列中(除第一个)任意一个元素就是其前一个元素的平方。举一个例子:
3^1 = 3
3^2 = (3^1)^2 = 3^2 = 9
3^3 = 3^1 * 3^2 = 3^3 = 3 * 9 = 27
3^4 = (3^2)^2 = 9^2 = 81
3^5 = 3^1 * 3^4 = 3^5 = 3 * 81 = 243
3^8 = (3^4)^2 = 81^2 = 6561
因此为了计算3^13,我们只需要将对应二进制位为1的整系数乘起来就行了:
3^13 = 6561 * 81 * 3 = 1594323
代码实现
首先我们可以直接按照上述递归方法实现:
// C++ Version long long binpow(long long a, long long b) { if (b == 0) return 1; long long res = binpow(a, b / 2); if (b % 2) return res * res * a; else return res * res; }
第二种实现方法是非递归式的。它在循环的过程中将二进制位为 1 时对应的幂累乘到答案中。尽管两者的理论复杂度是相同的,但第二种在实践过程中的速度是比第一种更快的,因为递归会花费一定的开销。
// C++ Version
long long binpow(long long a, long long b) {
long long res = 1;
while (b) {
if (b & 1) res = res * a;
a = a * a;
b >>= 1;
}
return res;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)