快速幂CSP-S

目录

💡 核心思想

快速幂在 $O(\log n)$ 时间内计算 $a^n \mod p$。核心是将指数按二进制分解:$a^n = a^{b_0 \cdot 2^0} \cdot a^{b_1 \cdot 2^1} \cdot \ldots$,其中 $b_i$ 是 $n$ 的二进制位。每次平方并按位累乘。

快速幂是竞赛中的"万金油"——数论题几乎都要用。代码只有几行但非常精妙:底数不断自平方,指数不断右移。如果当前位是 1 就把当前底数乘进答案。注意每步都要取模,防止溢出。

🎯 直觉理解

想象你要计算 $2^{13}$。朴素方法是乘 13 次。但 $13 = 1101_2$,所以 $2^{13} = 2^1 \times 2^4 \times 2^8$。你只需要算 $2^1, 2^2, 2^4, 2^8$(每次自乘),然后挑需要的乘起来——总共只需要 $\log 13 \approx 4$ 步。

📝 算法流程

  1. 初始化 ans = 1
  2. n 的每一位:如果为 1,ans *= a
  3. a = a * a(自平方)
  4. n >>= 1(右移一位)

$$a^n = \prod_{i: b_i = 1} a^{2^i} \pmod{p}$$

📊 复杂度分析

指标复杂度
时间$O(\log n)$
空间$O(1)$

💻 参考实现(C++)

C++ (C++17)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll qpow(ll a, ll n, ll mod) {
    ll ans = 1; a %= mod;
    while (n) {
        if (n & 1) ans = ans * a % mod;
        a = a * a % mod;
        n >>= 1;
    }
    return ans;
}
int main() {
    ll a, n, p; cin >> a >> n >> p;
    cout << qpow(a, n, p) << endl;
    return 0;
}

⚠️ 常见坑点

每步都要取模,不要只在最后取

a 要先 %= mod

n = 0 时结果应为 1(但要考虑 0^0)

快速幂可以推广到矩阵乘法

📚 相关题目

题目来源难度备注
P1226 快速幂洛谷CSP-S快速幂模板
P1962 斐波那契数列洛谷CSP-S矩阵快速幂