📌 什么是快速幂?

快速幂(Exponentiation by squaring) 是一种高效计算一个数的幂的方法。
相比于普通的循环乘法 a^b = a * a * ... * a(共 b 次),快速幂的时间复杂度为 O(log b),特别适合处理大指数的情况。


✅ 学习目标

  • 理解快速幂的基本思想
  • 掌握如何用 C++ 实现快速幂算法
  • 学会使用取模运算进行“模幂”运算(用于加密、竞赛等场景)
  • 提供完整代码和详细注释

🧠 快速幂原理讲解

我们以求 ab a^b 为例:

核心思想:

将指数 b b 分解成二进制形式,并利用平方操作减少乘法次数。

例如:$ a^{13} = a^{(8 + 4 + 1)} = a^8 \times a^4 \times a^1 $

我们可以不断将底数平方,同时判断当前位是否在二进制中为 1,如果是就乘到结果中。


🔢 基础版本:不带取模的快速幂

#include <iostream>
using namespace std;

// 快速幂函数(不取模)
long long fastPower(long long base, long long exponent) {
    long long result = 1; // 初始化结果为1

    while (exponent > 0) {              // 当指数大于0时继续循环
        if (exponent % 2 == 1) {        // 如果当前指数是奇数(即二进制最后一位是1)
            result = result * base;     // 就把当前底数乘入结果
        }
        base = base * base;             // 底数平方(相当于指数翻倍)
        exponent = exponent / 2;        // 指数除以2(右移一位)
    }

    return result;
}

int main() {
    long long a = 2;   // 底数
    long long b = 10;  // 指数

    cout << a << "^" << b << " = " << fastPower(a, b) << endl;
    return 0;
}

📌 输出示例:

2^10 = 1024

🔐 进阶版本:带取模的快速幂(模幂)

这是在密码学、算法竞赛中最常用的形式:计算 abmodm a^b \mod m

#include <iostream>
using namespace std;

// 快速幂取模函数
long long fastPowerMod(long long base, long long exponent, long long mod) {
    long long result = 1; // 结果初始化为1

    base = base % mod;    // 先对底数取模,防止初始值过大

    while (exponent > 0) {
        if (exponent % 2 == 1) {            // 如果当前指数是奇数
            result = (result * base) % mod; // 把当前底数乘入结果并取模
        }
        base = (base * base) % mod;         // 底数平方并取模
        exponent = exponent / 2;            // 指数除以2
    }

    return result;
}

int main() {
    long long a = 2;   // 底数
    long long b = 10;  // 指数
    long long m = 1000; // 模数

    cout << a << "^" << b << " mod " << m << " = " << fastPowerMod(a, b, m) << endl;
    return 0;
}

📌 输出示例:

2^10 mod 1000 = 24

📚 补充说明

参数名 含义
base 底数,即 a
exponent 指数,即 b
mod 取模值,可选

💡 使用场景推荐

场景 是否需要取模
计算非常大的幂 ✅ 是(否则可能溢出)
密码学(如 RSA 加密) ✅ 是
算法竞赛(如 ACM、蓝桥杯)
小规模幂运算 ❌ 否

⚠️ 注意事项

  1. 数据类型选择:建议使用 long long 防止中间结果溢出。
  2. 负指数问题:本教程不涉及负指数,若需要支持请加条件判断。
  3. 浮点数快速幂:也可实现浮点数幂运算,但需注意精度问题。

📝 总结

  • 快速幂是一个非常高效的幂运算方法。
  • 时间复杂度:O(log b),比 O(b) 快很多。
  • 在实际编程中,尤其是算法竞赛和密码学中,模幂运算尤为重要。
  • 推荐将模幂函数写成模板或封装成工具类函数,在多个项目中复用。

3 条评论

  • @ 2025-5-3 12:25:07

    用递归的方式实现快速幂算法

    下面为你详细介绍如何用递归方式实现快速幂算法,同时给出相应的代码及解释。

    递归思路

    递归实现快速幂算法的核心在于依据指数的奇偶性来分情况处理:

    • 当指数 n 为偶数时,ana^n 可转化为 (an/2)2(a^{n/2})^2
    • 当指数 n 为奇数时,ana^n 可转化为 a×an1a\times a^{n - 1}

    代码实现

    下面是使用 C++ 实现的递归快速幂算法,代码中添加了详细注释:

    #include <iostream>
    
    // 递归实现快速幂函数,计算 a 的 n 次幂
    long long recursiveFastPower(long long a, long long n) {
        // 若指数为 0,任何数的 0 次幂都为 1
        if (n == 0) {
            return 1;
        }
        // 若指数为偶数
        if (n % 2 == 0) {
            // 先计算 a 的 n/2 次幂
            long long temp = recursiveFastPower(a, n / 2);
            // 再将结果平方
            return temp * temp;
        } else {
            // 若指数为奇数,先计算 a 的 n - 1 次幂,再乘以 a
            return a * recursiveFastPower(a, n - 1);
        }
    }
    
    int main() {
        long long a = 2;  // 底数
        long long n = 13; // 指数
    
        // 调用递归快速幂函数计算结果
        long long result = recursiveFastPower(a, n);
    
        // 输出结果
        std::cout << a << " 的 " << n << " 次幂是: " << result << std::endl;
    
        return 0;
    }    
    

    代码解释

    1. 函数定义recursiveFastPower 函数接收两个参数 an,分别代表底数和指数,返回值为 ana^n 的结果。
    2. 基准情况:当 n 为 0 时,函数直接返回 1,因为任何数的 0 次幂都是 1。
    3. 指数为偶数的情况:若 n 为偶数,先递归计算 an/2a^{n/2} 的结果存储在 temp 中,再将 temp 平方得到最终结果。
    4. 指数为奇数的情况:若 n 为奇数,先递归计算 an1a^{n - 1} 的结果,再乘以 a 得到最终结果。
    5. 主函数:在 main 函数里,设定底数 a 和指数 n,调用 recursiveFastPower 函数计算结果并输出。

    复杂度分析

    • 时间复杂度O(logn)O(log n),由于每次递归时指数要么减半,要么减 1,所以递归深度为 O(logn)O(log n)
    • 空间复杂度O(logn)O(log n),递归调用栈的深度为 O(logn)O(log n)
    • @ 2025-5-3 12:24:13

      快速幂算法简介

      快速幂是一种高效计算幂运算的算法。通常,计算 ana^n 时,普通的方法是将 aa 连乘 nn 次,时间复杂度为 O(n)O(n)。而快速幂算法可以将时间复杂度降低到 O(logn)O(log n),大大提高了计算效率,尤其是当 nn 非常大的时候。

      原理

      快速幂算法的核心思想是利用指数的二进制表示。例如,要计算 a13a^{13},因为 1313 的二进制表示是 11011101,即 13=23+22+2013 = 2^3 + 2^2 + 2^0,那么 $a^{13} = a^{2^3 + 2^2 + 2^0} = a^{2^3} \times a^{2^2} \times a^{2^0}$。

      代码实现

      下面是一个用C++实现的快速幂算法的示例代码,包含详细的注释:

      #include <iostream>
      
      // 快速幂函数,计算 a 的 n 次幂
      long long fastPower(long long a, long long n) {
          long long result = 1;  // 初始化结果为 1
          long long base = a;    // 初始化底数为 a
      
          // 当指数 n 大于 0 时,继续循环
          while (n > 0) {
              // 如果 n 的二进制表示的最低位是 1
              if (n % 2 == 1) {
                  result *= base;  // 将当前的底数乘到结果中
              }
              base *= base;  // 底数平方
              n /= 2;        // 指数右移一位
          }
      
          return result;
      }
      
      int main() {
          long long a = 2;  // 底数
          long long n = 13; // 指数
      
          // 调用快速幂函数计算结果
          long long result = fastPower(a, n);
      
          // 输出结果
          std::cout << a << " 的 " << n << " 次幂是: " << result << std::endl;
      
          return 0;
      }
      

      代码解释

      1. 函数定义fastPower 函数接受两个参数 an,分别表示底数和指数,返回值为 ana^n 的结果。
      2. 初始化result 初始化为 1,用于存储最终结果;base 初始化为 a,表示当前的底数。
      3. 循环条件while (n > 0) 表示只要指数 n 大于 0,就继续循环。
      4. 判断最低位if (n % 2 == 1) 用于判断 n 的二进制表示的最低位是否为 1,如果是 1,则将当前的底数 base 乘到结果 result 中。
      5. 底数平方base *= base 表示将底数平方,相当于将指数翻倍。
      6. 指数右移n /= 2 表示将指数右移一位,相当于去掉二进制表示的最低位。
      7. 返回结果:循环结束后,返回最终的结果 result

      复杂度分析

      • 时间复杂度O(logn)O(log n),因为每次循环指数都会减半。
      • 空间复杂度O(1)O(1),只使用了常数级的额外空间。

      通过这种方式,你可以高效地计算幂运算,尤其是在处理大规模数据时,快速幂算法的优势会更加明显。

      • @ 2025-5-3 12:18:17

        快速幂是一种高效计算幂次的算法,它可以将计算 ana^n 的时间复杂度从朴素算法的 O(n)O(n) 降低到 O(logn)O(log n)。下面为你详细介绍快速幂算法的原理和实现,以及如何在 C++ 中实现它。

        原理

        快速幂算法的核心思想是利用幂次的二进制分解。假设我们要计算 ana^n,可以将 nn 表示为二进制形式,例如:n=21k+22k++2mkn = 2^k_1+2^k_2+\cdots+2^k_m。那么 ana^n 就可以写成 $a^{2^k_1}\times a^{2^k_2}\times\cdots\times a^{2^k_m}$。

        例如,计算 a13a^{13},因为 1313 的二进制表示是 11011101,即 13=23+22+2013 = 2^3 + 2^2 + 2^0,所以 a13=a23×a22×a20a^{13}=a^{2^3}\times a^{2^2}\times a^{2^0}

        代码实现

        以下是使用 C++ 实现快速幂的代码:

        #include <iostream>
        
        // 快速幂函数
        long long fastPower(long long a, long long n) {
            long long result = 1;
            while (n > 0) {
                if (n & 1) {  // 判断 n 的二进制最后一位是否为 1
                    result *= a;
                }
                a *= a;  // a 平方
                n >>= 1;  // n 右移一位,相当于除以 2
            }
            return result;
        }
        
        int main() {
            long long a = 2;
            long long n = 13;
            long long ans = fastPower(a, n);
            std::cout << a << " 的 " << n << " 次幂是: " << ans << std::endl;
            return 0;
        }
        

        代码解释

        1. 初始化结果result 初始化为 1,用于存储最终结果。
        2. 循环条件:当 n > 0 时,继续循环。
        3. 判断二进制最后一位:使用 n & 1 判断 n 的二进制最后一位是否为 1,如果是 1,则将当前的 a 乘到 result 中。
        4. 平方操作:将 a 平方,即 a *= a
        5. 右移操作:将 n 右移一位,相当于将 n 除以 2。
        6. 返回结果:当 n 变为 0 时,循环结束,返回 result

        复杂度分析

        • 时间复杂度O(logn)O(log n),因为每次循环 n 都会减半。
        • 空间复杂度O(1)O(1),只使用了常数级的额外空间。

        取模运算

        在实际应用中,幂次的结果可能会非常大,为了避免溢出,通常会对结果取模。以下是带有取模运算的快速幂代码:

        #include <iostream>
        
        const long long MOD = 1e9 + 7;
        
        // 带取模的快速幂函数
        long long fastPowerMod(long long a, long long n) {
            long long result = 1;
            a %= MOD;  // 防止 a 过大
            while (n > 0) {
                if (n & 1) {
                    result = (result * a) % MOD;
                }
                a = (a * a) % MOD;
                n >>= 1;
            }
            return result;
        }
        
        int main() {
            long long a = 2;
            long long n = 13;
            long long ans = fastPowerMod(a, n);
            std::cout << a << " 的 " << n << " 次幂对 " << MOD << " 取模的结果是: " << ans << std::endl;
            return 0;
        }
        

        这个代码在每次乘法操作后都对结果取模,确保结果不会溢出。

        • 1