基于二进制指数位拆分与乘数平方分流,将 $O(N)$ 的幂乘运算完美优化至极速 $O(\log N)$ 级别
如果我们需要求解 $a^b \bmod m$ 的值,最朴素的方法是将 $a$ 循环累乘 $b$ 次,时间复杂度为 $O(b)$。在信息学竞赛中,当 $b$ 达到 $10^{18}$ 规模时,必须使用快速幂(Fast Exponentiation)优化。
任何一个正整数指数 $b$ 都可以唯一地拆分为二进制表示形式:
根据幂底指数相乘法则,大幂次可以拆分为若干个 $a^{2^i}$ 的乘积之和:
💡 快速幂核心步骤:
- 我们从 $i=0$ 开始递增。在每一步中,底数 $a$ 不断自我平方:$a \leftarrow a^2 \bmod m$(对应大幂项 $a^{2^0}, a^{2^1}, a^{2^2}, \dots$ 递增倍增)。
- 检查指数 $b$ 的当前二进制最低位(b & 1):
- 若该位为 1(即 $c_i = 1$),则说明该倍增项被选中,我们将其乘入答案中:ans = ans * a % m;
- 若该位为 0,则忽略跳过,答案不变。
- 指数右移一位:b >>= 1,继续检测下一位。由于每次指数折半,仅需 $O(\log b)$ 次平方乘法即可求解!
long long qpow(long long a, long long b, long long m) {
long long ans = 1;
a %= m; // 基础底数取模
while (b > 0) {
if (b & 1) {
ans = (ans * a) % m; // 奇数次幂,乘当前权重并模除
}
a = (a * a) % m; // 底数平方倍增成下一项权重
b >>= 1; // 指数二进制右移一位
}
return ans;
}