快速幂原理
#c
快速幂算法旨在高效计算 。其核心思想是利用指数的二进制表示,将乘法次数减少到 级别。详细解释如下:
快速幂的思想
给定计算 ,如果 表示为二进制数(如 ),那么我们可以将其表示为:
这等价于:
代码逻辑逐步解释
long long mod_pow(long long a, long long b, long long m) {
long long result = 1; // 初始化结果为1,因为任何数的0次幂都是1。
a = a % m; // 确保a < m,避免不必要的大数计算。
while (b > 0) { // 当指数b大于0时,继续循环。
if (b % 2 == 1) { // 如果b是奇数,当前位是1,将a的当前幂次乘入结果。
result = (result * a) % m;
}
a = (a * a) % m; // 平方a,使其变为a的下一个2的幂次。
b /= 2; // 将b右移一位(相当于除以2),处理下一个二进制位。
}
return result; // 返回最终结果。
}
为什么只在 b % 2 == 1 时才乘 a?
- 我们需要在
b的二进制表示中,所有为 1 的位所对应的 累乘到result。 - 如果
b的当前位是 1(即b % 2 == 1),这意味着 是构成 所需的一个因子,因此要将a累乘到result。 - 如果
b的当前位是 0,说明 不需要参与乘积,因此跳过。
为什么在 return result; 时不乘 a?
- 在
while循环中,result已经累积了所有需要的 的乘积。 a已在每次迭代中通过a = (a * a) % m更新,用于计算更高次的幂,但只有当对应的b的二进制位为 1 时,才将其乘入result。- 退出循环时,
b已经被右移到 0(即已经处理完所有二进制位),result就是完整的乘积。 - 如果在
return时再乘以a,会导致额外的乘积,结果会错误,因为a在最后一次迭代中已经被平方或更新到一个更高次的幂。
举例
计算 :
b = 13_{10} = 1101_2,即 。- 初始化
result = 1。 - 迭代1(
b最低位是1):result = (result * a) % m,更新a = a^2 \mod m,b右移。 - 迭代2(
b当前位是0):不更新result,仅更新a = a^4 \mod m,b右移。 - 迭代3(
b当前位是1):result = (result * a) % m,更新a = a^8 \mod m,b右移。 - 迭代4(
b当前位是1):result = (result * a) % m,更新a = a^{16} \mod m,b右移。 b变为0,循环结束,返回result。
最终,result 累积了 ,即 的正确结果。