快速幂取模
快速幂取模通过二进制拆分指数,将大指数幂运算的时间复杂度降至 O (log n),在每一步运算中同步做取模操作,避免数值溢出,用来高效求解 a 的 b 次方对 m 取模的结果。
基础算法1分钟阅读

快速幂取模(Modular Exponentiation) 是快速幂算法在实际工程和算法竞赛中最常见的形态。
它专门用来高效计算类似 的问题,即求 的 次方对 取模的结果。
在计算机中,如果不做处理直接算 :
- 当 时, 已经高达 ,早已远超 64 位整型(
long long/uint64_64)的表示上限,导致整型溢出。 - 即便 Python 这种支持高精度大数的语言不会溢出,上千位甚至上万位的超大数乘法也会严重拖慢计算速度,耗尽内存。
根据模算术性质,乘积的模等于模的乘积:
这意味着:我们不需要等到整个指数算完再取模,而是在乘法执行的每一步都顺手取模。这样能把中间变量一直控制在 的安全范围内,完全杜绝溢出问题!
快速幂取模把指数 看作二进制数。
以计算 为例:
- 指数 的二进制是 ,即 。
- 所以 。
- 算法从最低位向最高位扫描 :
- 第 0 位(1): 包含 ,答案累乘 ,底数翻倍成 。
- 第 1 位(0): 不包含 ,答案不变,底数翻倍成 。
- 第 2 位(1): 包含 ,答案累乘 ,底数翻倍成 。
- 第 3 位(1): 包含 ,答案累乘 。
每一步的累乘和底数自乘,都立刻对 取模。
在实现时,有两个极易被忽视的坑点需要特别注意:
- 防止 :传入前先做
a = a % m。 - 中间乘法溢出:两个小于 的数相乘,最大可能达到 。如果 ,乘积就会达到 ,必须用 64 位整数(如 C++ 的
long long)来存储中间结果。
#include <iostream>
// 计算 (a^b) % mlong long fast_power_mod(long long a, long long b, long long m) { long long ans = 1; a %= m; // 防止 a 本身比 m 大
while (b > 0) { // 如果 b 的当前二进制最低位为 1 if (b & 1) { ans = (ans * a) % m; // 累乘当前权重的底数,并取模 } a = (a * a) % m; // 底数自乘翻倍,并取模 b >>= 1; // b 右移一位,相当于 b /= 2 }
return ans;}
int main() { // 示例:计算 (2^1000) % 1000000007 std::cout << fast_power_mod(2, 1000, 1000000007) << std::endl; return 0;}| 指标 | 复杂度 / 描述 |
|---|---|
| 时间复杂度 | — 循环次数仅取决于 的二进制位数。 |
| 空间复杂度 | — 仅需几个常数级别的变量存放中间值。 |
- 密码学(RSA 加密算法): RSA 的核心解密/加密公式就是大数快速幂取模,例如 ,其中指数 和模数 通常长达 2048 位。
- 求乘法逆元: 基于费马小定理( 为质数时,),取模意义下的逆元 可以通过计算 直接获得。
- 米勒-拉宾(Miller-Rabin)素数测试: 极其高效的大数概率素数检测算法,核心依赖快速幂取模。