快速幂(Fast Exponentiation):计算 a^n mod p,将 O(n) 优化到 O(log n)。
🔍 倍增思想在快速幂中的体现
核心等式:a^(2k) = (a^k)²,a^(2k+1) = (a^k)² × a
例:计算 3^13 = 3^(8+4+1) = 3^8 × 3^4 × 3^1
预处理:3^1 = 3, 3^2 = 9, 3^4 = 81, 3^8 = 6561
3^13 = 6561 × 81 × 3 = 1594323
只需 log₂13 ≈ 4 次乘法,而不是 13 次!
C++fast_pow.cpp — 快速幂
long long fast_pow(long long a, long long n, long long p) {
long long result = 1;
a %= p;
while (n > 0) {
if (n & 1) // n 的最低位为 1
result = result * a % p;
a = a * a % p; // a = a^(2^j)
n >>= 1; // n 右移一位
}
return result;
}
快速幂利用倍增思想,将 n 按二进制分解,每轮将 n 右移一位(除以2),共 log₂n 轮。每轮最多2次乘法。
考点:快速幂把指数按二进制分解,循环轮数与指数的二进制位数同阶。
易错:把快速幂的复杂度写成 O(n)(那是朴素连乘 n 次的做法),或误答 O(log²n)。
A4编程题
用快速幂计算 3^100 mod 1000000007,写出完整代码。
查看参考答案
#include<iostream>using namespace std;
long long fast_pow(long long a, long long n, long long p) {
long long res = 1;
a %= p;
while(n > 0) {
if(n & 1) res = res * a % p;
a = a * a % p;
n >>= 1;
}
return res;
}
int main() {
cout << fast_pow(3, 100, 1000000007) << endl;
return0;
}
long long dis[MAXN]; // 到根的距离void dfs(int u, int p, long long d) {
dis[u] = d; dep[u] = dep[p] + 1;
up[u][0] = p;
for(int j=1;j<LOG;j++) up[u][j]=up[up[u][j-1]][j-1];
for(auto& e : adj[u]) if(e.to != p)
dfs(e.to, u, d + e.w);
}
// 查询long long dist(int u, int v) {
return dis[u] + dis[v] - 2 * dis[lca(u, v)];
}
原理:u 到 v 的路径 = u→LCA + LCA→v。dis[u]-dis[LCA] 是 u 到 LCA 的距离,dis[v]-dis[LCA] 是 v 到 LCA 的距离。
typedef long long ll;
const ll MOD = 1000000007;
struct Mat { ll m[2][2]; };
Mat mul(Mat A, Mat B) {
Mat C={{{0,0},{0,0}}};
for(int i=0;i<2;i++)
for(int k=0;k<2;k++)
for(int j=0;j<2;j++)
C.m[i][j]=(C.m[i][j]+A.m[i][k]*B.m[k][j])%MOD;
return C;
}
Mat mpow(Mat A, ll p) {
Mat R={{{1,0},{0,1}}};
while(p>0) { if(p&1) R=mul(R,A); A=mul(A,A); p>>=1; }
return R;
}
int main() {
ll n; cin >> n;
if(n<=2) { cout << 1; return0; }
Mat T={{{1,1},{1,0}}};
Mat R = mpow(T, n-2);
ll ans = (R.m[0][0]*1 + R.m[0][1]*1) % MOD;
cout << ans << endl;
}