思路:对b用二进制表示,分开操作防止溢出。
对b用二进制表示:
b=b0∗20+b1∗21+b2∗22+...+bn∗2n,bi=0 or 1,i=0,..,nb=b_0*2^0+b_1*2^1+b_2*2^2+...+b_n*2^n,b_i=0 \ or\ 1,i=0,..,nb=b0∗20+b1∗21+b2∗22+...+bn∗2n,bi=0 or 1,i=0,..,n
ab=ab0∗20+b1∗21+b2∗22+...+bn∗2n=ab0∗20∗ab1∗21∗...∗abn∗2na^b=a^{b_0*2^0+b_1*2^1+b_2*2^2+...+b_n*2^n}=a^{b_0*2^0}*a^{b_1*2^1}*...*a^{b_n*2^n}ab=ab0∗20+b1∗21+b2∗22+...+bn∗2n=ab0∗20∗ab1∗21∗...∗abn∗2n
a的b次方对p取模,每次累乘abi∗2ia^{b_i*2^i}abi∗2i后立即取模,这样不会溢出。
a∗b=a∗(b0∗20+b1∗21+b2∗22+...+bn∗2n)=a∗b0∗20+a∗b1∗21+...+a∗bn∗2na*b=a*(b_0*2^0+b_1*2^1+b_2*2^2+...+b_n*2^n)=a*b_0*2^0+a*b_1*2^1+...+a*b_n*2^na∗b=a∗(b0∗20+b1∗21+b2∗22+...+bn∗2n)=a∗b0∗20+a∗b1∗21+...+a∗bn∗2n
a乘b对p取模,每次累加a∗bi∗2ia*b_i*2^ia∗bi∗2i后立即取模,这样不会溢出。
时间复杂度,两者都是b拆开后的项数,O(⌊log2b⌋+1)≈O(logb)O(\lfloor{log_2b}\rfloor+1) \approx O(logb)O(⌊log2b⌋+1)≈O(logb)
a = 4
b = 3
p = 3
def quick_power(a, b, p):
tmp,sum = 1, 1
while b:
tmp = tmp*a%p
if b&1:
sum = sum*tmp%p
b >>= 1
return sum
print(quick_power(a, b, p))
def quick_mul(a, b, p):
sum, tmp = 0, 1
flag = False
while b:
if not flag:
tmp *= 1
flag = True
else:
tmp = tmp*2%p
if b&1:
sum = (sum + a*tmp)%p
b >>= 1
return sum
print(quick_mul(a, b, p))
这篇博客介绍了两种高效的算法:快速幂运算(quick_power)和快速乘法(quick_mul),用于计算大整数的乘方和乘法,并在模运算下防止溢出。算法通过将b转化为二进制表示,然后逐位处理,将时间复杂度降低到大约O(logb)。在给定的示例中,a=4, b=3, p=3,两个函数分别计算了4的3次方和4乘以3的结果,对3取模。
1923

被折叠的 条评论
为什么被折叠?



