算法基础 -- 快速幂算法详解

快速幂算法详解

快速幂(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 时,可以利用以下两个数学性质:

  1. 幂的拆分

    • a n = a × a n − 1 a^n = a \times a^{n-1} an=a×an1,如果 n n n 是奇数;
    • a n = ( a n / 2 ) 2 a^n = (a^{n/2})^2 an=(an/2)2,如果 n n n 是偶数。
  2. 平方快速翻倍

    如果已经知道 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×an1

通过不断折半,我们最终可以将计算复杂度降低到 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 1
    if n == 1:
        return a

    if n is even:
        half = fastPower(a, n // 2)
        return half * half
    else:
        return a * fastPower(a, n - 1)

2. 迭代实现

迭代实现通过“处理指数的二进制位”来实现。思路如下:

  1. 准备结果变量 res = 1,初始幂底 base = a
  2. 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)。
  3. 循环结束时,res 即为最终结果。

伪代码如下:

function fastPowerIterative(a, n):
    res = 1
    base = a
    while n > 0:
        if (n & 1) == 1:
            res = res * base
        base = base * base
        n >>= 1
    return res

3. 快速幂取模

在许多实际问题中,需要计算 a n   m o d   m a^n \bmod m anmodm。此时可在每次乘法后加入取模操作,避免中间结果过大:

function fastPowerMod(a, n, m):
    res = 1
    base = a % m
    while n > 0:
        if (n & 1) == 1:
            res = (res * base) % m
        base = (base * base) % m
        n >>= 1
    return res

通过每次取模操作,可以确保数值始终在合理范围内,不会溢出。


三、示例演算

示例 1:递归实现

计算 3 13 3^{13} 313

  1. n = 13 n = 13 n=13 是奇数,结果为 3 × 3 12 3 \times 3^{12} 3×312
  2. 3 12 = ( 3 6 ) 2 3^{12} = (3^6)^2 312=(36)2
  3. 3 6 = ( 3 3 ) 2 3^6 = (3^3)^2 36=(33)2
  4. 3 3 = 3 × 3 2 3^3 = 3 \times 3^2 33=3×32
  5. 3 2 = ( 3 1 ) 2 3^2 = (3^1)^2 32=(31)2
  6. 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

  1. res = 1, base = 3, n = 13(1101)
  2. 低位是 1:更新 res = 1 * 3 = 3;更新 base = 3^2 = 9,右移 n = 110 n = 110 n=110
  3. 低位是 0:跳过 res 更新;更新 base = 9^2 = 81,右移 n = 11 n = 11 n=11
  4. 低位是 1:更新 res = 3 * 81 = 243;更新 base = 81^2 = 6561,右移 n = 1 n = 1 n=1
  5. 低位是 1:更新 res = 243 * 6561 = 1594323;更新 base = 6561^2 = 43046721,右移 n = 0 n = 0 n=0
  6. 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)(仅需常量存储)。

五、总结

  1. 核心思想:利用幂次的奇偶性和二进制表示,逐步将规模缩小到对数级别。
  2. 常见应用
    • 大数运算:计算 a n a^n an 的值;
    • 模运算:如 a n   m o d   m a^n \bmod m anmodm
    • 矩阵快速幂:用于斐波那契数列等问题。
  3. 实现要点
    • 按指数奇偶分类,折半处理;
    • 取模时加上每次乘法后的模操作,防止溢出。

你可能感兴趣的:(算法,数据结构)