快速幂算法详解
快速幂(Exponentiation by Squaring)是一种高效计算 abmod ca^b \mod cabmodc 的方法,特别适用于处理大整数幂的场景。
1. 什么是快速幂?
快速幂的核心思想是将幂次拆分成二进制形式,通过平方和乘法逐步计算结果,而不是直接进行 bbb 次乘法。其时间复杂度从普通幂的 O(b)O(b)O(b) 降低到 O(logb)O(\log b)O(logb)。
2. 数学基础
幂运算的规律
对于一个数 aaa 和整数幂 bbb:
- 如果 bbb 是偶数:ab=(ab/2)2a^b = (a^{b/2})^2ab=(ab/2)2
- 如果 bbb 是奇数:ab=a⋅ab−1a^b = a \cdot a^{b-1}ab=a⋅ab−1
3. 快速幂的思想
通过幂次的二进制拆解,可以将幂次逐步减少:
- 偶数幂:我们只需平方当前底数。
- 奇数幂:先记录当前底数为部分结果,然后减少幂次(变为偶数)。
快速幂的分解过程
假设 b=13b = 13b=13,二进制为 110111011101,我们计算 a13a^{13}a13:
- 将 131313 拆解为 a13=a8⋅a4⋅a1a^{13} = a^{8} \cdot a^{4} \cdot a^{1}a13=a8⋅a4⋅a1(二进制中为 1 的位对应的幂次)。
- 通过平方底数逐步计算:
- a1=aa^1 = aa1=a
- a2=a⋅aa^2 = a \cdot aa2=a⋅a
- a4=(a2)2a^4 = (a^2)^2a4=(a2)2
- a8=(a4)2a^8 = (a^4)^2a8=(a4)2
- 将对应的幂次相乘即可。
4. 快速幂实现
4.1 递归实现
递归方式按照 bbb 的奇偶性进行拆解。
代码实现
public class FastPower {
public static long fastPower(long a, long b, long mod) {
if (b == 0) return 1; // 任何数的 0 次幂是 1
long half = fastPower(a, b / 2, mod); // 递归计算一半的幂
long result = (half * half) % mod; // 平方取模
// 如果 b 是奇数,还需要多乘一个 a
if (b % 2 != 0) {
result = (result * a) % mod;
}
return result;
}
public static void main(String[] args) {
System.out.println(fastPower(2, 10, 1000000007)); // 输出 1024
}
}
流程解析
- 如果 b=0b = 0b=0,返回 111。
- 否则递归计算 ab/2a^{b/2}ab/2。
- 将其平方,如果 bbb 是奇数,则额外乘以 aaa。
4.2 迭代实现
迭代方式直接通过 bbb 的二进制位逐位计算。
代码实现
public class FastPower {
public static long fastPower(long a, long b, long mod) {
long result = 1; // 初始化结果为 1
long base = a % mod; // 计算 a 的初始模
while (b > 0) {
// 如果 b 的当前位是 1,将当前 base 累乘到结果
if ((b & 1) == 1) {
result = (result * base) % mod;
}
base = (base * base) % mod; // 底数平方
b >>= 1; // b 右移一位,相当于 b // 2
}
return result;
}
public static void main(String[] args) {
System.out.println(fastPower(2, 10, 1000000007)); // 输出 1024
System.out.println(fastPower(2, 1000, 1000000007)); // 输出大数结果
}
}
流程解析
- 初始化
result = 1
,base = a % mod
。 - 遍历幂次的二进制表示(通过右移逐步处理)。
- 如果当前位为
1
,累乘当前base
到result
。 - 每次循环后,
base
自身平方,b
右移一位。
5. 示例分析
示例 1:普通幂运算
计算 2102^{10}210,无取模:
- b=10b = 10b=10,二进制为
1010
。 - 拆解为 210=(28)⋅(22)2^{10} = (2^8) \cdot (2^2)210=(28)⋅(22)。
- 迭代过程:
以下是 快速幂算法在计算 2102^{10}210 的每一步执行过程中的 b
(当前幂次的二进制表示)、base
(当前底数)、result
(累积结果)的状态变化表:
初始值:
- b: 1010 (二进制表示 10)
- base: 2
- result: 1
迭代过程:
步骤 | b (二进制) | b (十进制) | 最低位 | 操作 | base | result |
---|---|---|---|---|---|---|
初始值 | 1010 | 10 | 0 | 不更新 result ,base = base^2 | 4 | 1 |
第 1 步 | 0101 | 5 | 1 | 累乘到 result = result * base ,平方 base | 16 | 4 |
第 2 步 | 0010 | 2 | 0 | 不更新 result ,base = base^2 | 256 | 4 |
第 3 步 | 0001 | 1 | 1 | 累乘到 result = result * base ,平方 base | 65536 | 1024 |
结束 | 0000 | 0 | - | 停止循环 | - | 1024 |
每一步详细解析
初始值:
- b = 1010,最低位为
0
。 - 因为最低位为
0
,不更新result
。 - 将
base
平方:base=22=4base = 2^2 = 4base=22=4。
第 1 步:
- b = 0101,最低位为
1
。 - 累乘到
result
:result=1⋅4=4result = 1 \cdot 4 = 4result=1⋅4=4。 - 将
base
平方:base=42=16base = 4^2 = 16base=42=16。 - 右移
b
:b = 0010。
第 2 步:
- b = 0010,最低位为
0
。 - 因为最低位为
0
,不更新result
。 - 将
base
平方:base=162=256base = 16^2 = 256base=162=256。 - 右移
b
:b = 0001。
第 3 步:
- b = 0001,最低位为
1
。 - 累乘到
result
:result=4⋅256=1024result = 4 \cdot 256 = 1024result=4⋅256=1024。 - 将
base
平方:base=2562=65536base = 256^2 = 65536base=2562=65536(虽然此时不会再用到base
)。 - 右移
b
:b = 0000。
结束:
- b = 0000,停止迭代。
- 最终结果:result=1024result = 1024result=1024。
总结
在快速幂算法中,每一位的处理都是通过平方更新 base
,并根据最低位的值决定是否累乘到 result
。这种方法使计算效率达到 O(logb)O(\log b)O(logb)。
示例 2:幂模运算
计算 210mod 72^{10} \mod 7210mod7:
- b=10b = 10b=10,二进制为
1010
。 - 拆解为 210mod 7=(28mod 7)⋅(22mod 7)mod 72^{10} \mod 7 = (2^8 \mod 7) \cdot (2^2 \mod 7) \mod 7210mod7=(28mod7)⋅(22mod7)mod7。
- 迭代过程:
- 初始:
result = 1
,base = 2
- 第 1 步:b=1010b = 1010b=1010,最低位为 0,不更新
result
。 - 第 2 步:b=0101b = 0101b=0101,最低位为 1,
result = 2
。 - 第 3 步:b=0010b = 0010b=0010,最低位为 0,不更新
result
。 - 第 4 步:b=0001b = 0001b=0001,最低位为 1,
result = 4
。
- 初始:
结果为 4
。
6. 时间与空间复杂度
时间复杂度
快速幂算法的时间复杂度为 O(logb)O(\log b)O(logb),因为每次运算将 bbb 减半(右移一位)。
空间复杂度
- 递归实现:需要 O(logb)O(\log b)O(logb) 的递归栈空间。
- 迭代实现:仅使用常数空间,空间复杂度为 O(1)O(1)O(1)。
7. 快速幂的应用场景
-
大数幂运算:
- 例如 210002^{1000}21000,直接计算会溢出,而快速幂可以通过取模解决。
-
密码学:
- 在 RSA 等加密算法中,经常需要计算 abmod ca^b \mod cabmodc,快速幂是核心部分。
-
组合数学与数论:
- 计算模逆元(利用费马小定理:a−1≡ap−2mod pa^{-1} \equiv a^{p-2} \mod pa−1≡ap−2modp,ppp 为质数)。
- 处理排列、组合时涉及的幂运算。
8. 总结
- 核心思想:利用幂的二进制拆解,通过平方和乘法快速计算结果。
- 递归实现:简单易懂,但需要栈空间。
- 迭代实现:效率高,占用空间少,更常用。
- 时间复杂度:O(logb)O(\log b)O(logb),适用于大规模运算场景。
掌握快速幂算法是学习数学、算法与密码学的基础技能,非常重要。