来源:洛谷89题
简单的(a**b)mod p会出现超时错误,因此了解了快速幂算法,此外,利用python库中的pow(a,b,p)也可解决。
算法简介:
快速幂算法(Fast Power Algorithm),也称为快速幂取模,是一种高效计算大整数幂的算法,特别适用于计算的场景,其中 a 是底数,b 是指数,p 是模数。任何正整数b都可以表示为二进制数。快速幂算法利用这一性质,通过递归地将指数b分解为一系列的2的幂次之和,从而将幂运算转化为一系列基于较小幂次的运算。
算法原理:
快速幂算法的核心在于指数的二进制分解,每次迭代实际上是在处理指数的一位。通过连续平方再取模,我们实际上是按照 a 的指数倍增序列(a,a^2,a^4,a^8,...) 进行计算,并选择性地将这些平方结果相乘(依据 b 的二进制表示中的 1),这样做大大减少了乘法的次数。
算法步骤:
-
分解指数:将指数 b 表示成二进制形式。
-
递归计算:根据指数的二进制位,从最低位到最高位(或反向处理),对于每一位:
- 如果当前位为1,则结果乘以当前的底数后取模(ans=ans*a mod p)。
- 底数 a 在每处理一位后都要平方一次(a=a^2 mod p),下一次乘法时使用的实际上是更高次幂的底数。
- 通常初始化时 ans=1(因为任何数的0次幂都是1),并且在处理完所有二进制位后,ans 即为所求
举例子说明:
效率分析:
快速幂算法的时间复杂度为 O(logb),这是因为我们只需要遍历 b 的二进制表示,而 b 的位数最多是 log2b。相比直接计算 a^b 后取模O(b),特别是在 b 非常大时,这种算法极大地减少了计算量和所需时间。
代码实现:
def quick_power(a, n, m):
ans = 1
a = a % m # 防止a很大时溢出
while n > 0:
# 如果当前位是1,将结果乘以a的当前幂次
if n % 2 == 1:
ans = (ans * a) % m
a = (a * a) % m
n //= 2
return ans
print(quick_power(2,13,1000))
print(pow(2,13,1000))