快速幂算法详解
快速幂(Fast Power或Exponentiation by Squaring)是一种能够在 O ( log n ) O(\log n) O(logn) 时间复杂度内高效计算幂次(如 a n a^n an)的算法。相比于朴素的逐次相乘(需要 O ( n ) O(n) O(n) 次乘法),快速幂极大地减少了运算次数,尤其当指数 n n n 较大时更显优势。以下从原理、实现思路及具体示例三个方面详细讲解。
一、快速幂的基本原理
计算 a n a^n an 时,可以利用以下两个数学性质:
-
幂的拆分
- a n = a × a n − 1 a^n = a \times a^{n-1} an=a×an−1,如果 n n n 是奇数;
- a n = ( a n / 2 ) 2 a^n = (a^{n/2})^2 an=(an/2)2,如果 n n n 是偶数。
-
平方快速翻倍
如果已经知道 a k a^k ak,那么:
a 2 k = ( a k ) 2 a^{2k} = (a^k)^2 a2k=(ak)2
通过上述性质,我们可以每次将指数 n n n 的规模减半,从而实现对数级别的处理。
- 当 n n n 为偶数:
a n = ( a n / 2 ) 2 a^n = (a^{n/2})^2 an=(an/2)2 - 当 n n n 为奇数:
a n = a × a n − 1 a^n = a \times a^{n-1} an=a×an−1
通过不断折半,我们最终可以将计算复杂度降低到 O ( log n ) O(\log n) O(logn)。
二、快速幂的实现思路
实现快速幂的方法包括 递归 和 迭代,常用的是基于“二进制指数拆分”的迭代实现。
1. 递归实现
递归的基本思路是不断将 n n n 按奇偶拆分,直到基准情况(如 n = 0 n=0 n=0 或 n = 1 n=1 n=1)。伪代码如下:
function fastPower(a, n):if n == 0:return 1if n == 1:return aif n is even:half = fastPower(a, n // 2)return half * halfelse:return a * fastPower(a, n - 1)
2. 迭代实现
迭代实现通过“处理指数的二进制位”来实现。思路如下:
- 准备结果变量
res = 1
,初始幂底base = a
。 - 当 n > 0 n > 0 n>0 时,依次处理 n n n 的二进制最低位:
- 如果最低位是 1(即 n n n 为奇数),则更新结果
res = res * base
; - 无论奇偶,都将
base = base * base
; - 将 n n n 右移一位(
n >>= 1
,即 n ÷ 2 n \div 2 n÷2)。
- 如果最低位是 1(即 n n n 为奇数),则更新结果
- 循环结束时,
res
即为最终结果。
伪代码如下:
function fastPowerIterative(a, n):res = 1base = awhile n > 0:if (n & 1) == 1:res = res * basebase = base * basen >>= 1return res
3. 快速幂取模
在许多实际问题中,需要计算 a n m o d m a^n \bmod m anmodm。此时可在每次乘法后加入取模操作,避免中间结果过大:
function fastPowerMod(a, n, m):res = 1base = a % mwhile n > 0:if (n & 1) == 1:res = (res * base) % mbase = (base * base) % mn >>= 1return res
通过每次取模操作,可以确保数值始终在合理范围内,不会溢出。
三、示例演算
示例 1:递归实现
计算 3 13 3^{13} 313:
- n = 13 n = 13 n=13 是奇数,结果为 3 × 3 12 3 \times 3^{12} 3×312;
- 3 12 = ( 3 6 ) 2 3^{12} = (3^6)^2 312=(36)2;
- 3 6 = ( 3 3 ) 2 3^6 = (3^3)^2 36=(33)2;
- 3 3 = 3 × 3 2 3^3 = 3 \times 3^2 33=3×32;
- 3 2 = ( 3 1 ) 2 3^2 = (3^1)^2 32=(31)2;
- 3 1 = 3 3^1 = 3 31=3。
最终结果为 3 13 = 1594323 3^{13} = 1594323 313=1594323。
示例 2:迭代实现
计算 3 13 3^{13} 313,其二进制表示为 13 = 110 1 2 13 = 1101_2 13=11012:
res = 1, base = 3, n = 13(1101)
。- 低位是 1:更新
res = 1 * 3 = 3
;更新base = 3^2 = 9
,右移 n = 110 n = 110 n=110。 - 低位是 0:跳过
res
更新;更新base = 9^2 = 81
,右移 n = 11 n = 11 n=11。 - 低位是 1:更新
res = 3 * 81 = 243
;更新base = 81^2 = 6561
,右移 n = 1 n = 1 n=1。 - 低位是 1:更新
res = 243 * 6561 = 1594323
;更新base = 6561^2 = 43046721
,右移 n = 0 n = 0 n=0。 - n = 0 n = 0 n=0,循环结束,结果为 1594323 1594323 1594323。
四、时间复杂度分析
每次将 n n n 减半,因此时间复杂度为 O ( log n ) O(\log n) O(logn),这是快速幂最显著的优势。
- 递归的空间复杂度: O ( log n ) O(\log n) O(logn)(递归深度)。
- 迭代的空间复杂度: O ( 1 ) O(1) O(1)(仅需常量存储)。
五、总结
- 核心思想:利用幂次的奇偶性和二进制表示,逐步将规模缩小到对数级别。
- 常见应用:
- 大数运算:计算 a n a^n an 的值;
- 模运算:如 a n m o d m a^n \bmod m anmodm;
- 矩阵快速幂:用于斐波那契数列等问题。
- 实现要点:
- 按指数奇偶分类,折半处理;
- 取模时加上每次乘法后的模操作,防止溢出。