对于a的n次方,如果我们老老实实用a每次的结果乘以自身的话,那需要乘n次,在n很大的时候速度很慢,但是,如果我们将n用二进制表示,这样就可以将乘法次数降到log(n)次。
def pickPow(a,b):
s=1
while b>0:
if b&1:s*=a
a*=a
b>>=1
return s
其实就是快速幂与求余性质的结合,由公式2推导出来(有人评论区问再追加证明过程),这里直接上代码,简单易懂。
def qickPowMod(a,b,p):
res=1
a=a%p
while b>0:
if b&1:res=(res*a)%p
a=(a*a)%p
b>>=1
return res
随着b的增大快速幂的运行速度的优势是很明显的
-----------当b为60时-----------
快速幂取余结果 1
常规求余结果 1
快速求余耗时: 0.0 常规求余耗时 0.0
-----------当b为674时-----------
快速幂取余结果 4
常规求余结果 4
快速求余耗时: 0.0 常规求余耗时 0.0
-----------当b为6759时-----------
快速幂取余结果 1
常规求余结果 1
快速求余耗时: 0.0 常规求余耗时 0.0
-----------当b为67630时-----------
快速幂取余结果 2
常规求余结果 2
快速求余耗时: 0.0 常规求余耗时 0.02298712730407715
-----------当b为676357时-----------
快速幂取余结果 2
常规求余结果 2
快速求余耗时: 0.0 常规求余耗时 0.48773908615112305
-----------当b为6763614时-----------
快速幂取余结果 1
常规求余结果 1
快速求余耗时: 0.0 常规求余耗时 18.909112215042114
欧拉函数就是对1-n上n的质数的个数的统计。
def oula(n):
s=n
i=2
while i*i<=n:
if n%i==0:
s=s//i*(i-1)
while n%i==0:
n=n//i
i+=1
if n>1:s=s//n*(n-1)
return s
再一般情况下,我们认为,用快速幂求余就已经够用了,但是,随着b的不断增大,快速幂也不那么好使了,特别是当b的大小远大于p的这时候,那有什么方法解决吗?这时候欧拉降幂就上场了。(欧拉真伟大!)
手撕欧拉降幂公式。
上代码
def oula(n):
s=n
i=2
while i*i<=n:
if n%i==0:
s=s//i*(i-1)
while n%i==0:
n=n//i
i+=1
if n>1:s=s//n*(n-1)
return s
def qickPowMod(a,b,p):
res=1
a=a%p
while b>0:
if b&1:res=(res*a)%p
a=(a*a)%p
b>>=1
return res
a,b,p=1000,20000000,100007
phi=oula(p)
if b<phi:
print(qickPowMod(a,b,p))
elif b==phi:
print(qickPowMod(a,b%phi,p))
else:
print(qickPowMod(a, b % phi+phi, p))
在快速幂求余算法与正常求余算法的对比中,当b达到6000000左右,普通的求余算法就基本上完全败下阵来,但是通过下面的例子我们可以发现,欧拉公式在b的数目惊人的巨大时,欧拉降幂还是略占上风,但是两公式在处理这么大数时的能力,还是让人惊叹。
-----------当b为92时-----------
快速幂取余结果 99722
常规求余结果 99722
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为945时-----------
快速幂取余结果 44531
常规求余结果 44531
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为9465时-----------
快速幂取余结果 94567
常规求余结果 94567
快速求余耗时: 0.0009984970092773438 欧拉求余耗时 0.0
-----------当b为94673时-----------
快速幂取余结果 66143
常规求余结果 66143
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为946744时-----------
快速幂取余结果 67063
常规求余结果 67063
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为9467467时-----------
快速幂取余结果 35213
常规求余结果 35213
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为94674673时-----------
快速幂取余结果 2816
常规求余结果 2816
快速求余耗时: 0.0010008811950683594 欧拉求余耗时 0.0
-----------当b为946746784时-----------
快速幂取余结果 62917
常规求余结果 62917
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为9467467899时-----------
快速幂取余结果 3368
常规求余结果 3368
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为94674679053时-----------
快速幂取余结果 71992
常规求余结果 71992
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为946746790617时-----------
快速幂取余结果 35882
常规求余结果 35882
快速求余耗时: 0.0009965896606445312 欧拉求余耗时 0.0
-----------当b为9467467906195时-----------
快速幂取余结果 70323
常规求余结果 70323
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为94674679062013时-----------
快速幂取余结果 72490
常规求余结果 72490
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为946746790620147时-----------
快速幂取余结果 4489
常规求余结果 4489
快速求余耗时: 0.0009996891021728516 欧拉求余耗时 0.0
-----------当b为9467467906201479时-----------
快速幂取余结果 20770
常规求余结果 20770
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为94674679062014806时-----------
快速幂取余结果 4117
常规求余结果 4117
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为946746790620148136时-----------
快速幂取余结果 17231
常规求余结果 17231
快速求余耗时: 0.0009989738464355469 欧拉求余耗时 0.0
-----------当b为9467467906201481441时-----------
快速幂取余结果 59935
常规求余结果 59935
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为94674679062014814477时-----------
快速幂取余结果 25432
常规求余结果 25432
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为946746790620148144853时-----------
快速幂取余结果 25075
常规求余结果 25075
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为9467467906201481448612时-----------
快速幂取余结果 32323
常规求余结果 32323
快速求余耗时: 0.0010006427764892578 欧拉求余耗时 0.0
-----------当b为94674679062014814486147时-----------
快速幂取余结果 95572
常规求余结果 95572
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为946746790620148144861569时-----------
快速幂取余结果 44531
常规求余结果 44531
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为9467467906201481448615727时-----------
快速幂取余结果 25652
常规求余结果 25652
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为94674679062014814486157273时-----------
快速幂取余结果 60137
常规求余结果 60137
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为946746790620148144861572807时-----------
快速幂取余结果 66748
常规求余结果 66748
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为9467467906201481448615728091时-----------
快速幂取余结果 54099
常规求余结果 54099
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为94674679062014814486157280994时-----------
快速幂取余结果 18203
常规求余结果 18203
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为946746790620148144861572809945时-----------
快速幂取余结果 67232
常规求余结果 67232
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为9467467906201481448615728099532时-----------
快速幂取余结果 93001
常规求余结果 93001
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为94674679062014814486157280995354时-----------
快速幂取余结果 89895
常规求余结果 89895
快速求余耗时: 0.0009992122650146484 欧拉求余耗时 0.0
-----------当b为946746790620148144861572809953541时-----------
快速幂取余结果 92587
常规求余结果 92587
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为9467467906201481448615728099535444时-----------
快速幂取余结果 15833
常规求余结果 15833
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为94674679062014814486157280995354479时-----------
快速幂取余结果 87191
常规求余结果 87191
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为946746790620148144861572809953544834时-----------
快速幂取余结果 63932
常规求余结果 63932
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为9467467906201481448615728099535448387时-----------
快速幂取余结果 67025
常规求余结果 67025
快速求余耗时: 0.0010018348693847656 欧拉求余耗时 0.0
-----------当b为94674679062014814486157280995354483921时-----------
快速幂取余结果 11449
常规求余结果 11449
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为946746790620148144861572809953544839233时-----------
快速幂取余结果 19117
常规求余结果 19117
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为9467467906201481448615728099535448392356时-----------
快速幂取余结果 2322
常规求余结果 2322
快速求余耗时: 0.0 欧拉求余耗时 0.0010187625885009766
-----------当b为94674679062014814486157280995354483923638时-----------
快速幂取余结果 94579
常规求余结果 94579
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为946746790620148144861572809953544839236430时-----------
快速幂取余结果 64850
常规求余结果 64850
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为9467467906201481448615728099535448392364357时-----------
快速幂取余结果 20630
常规求余结果 20630
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为94674679062014814486157280995354483923643609时-----------
快速幂取余结果 37633
常规求余结果 37633
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为946746790620148144861572809953544839236436117时-----------
快速幂取余结果 38478
常规求余结果 38478
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为9467467906201481448615728099535448392364361203时-----------
快速幂取余结果 58295
常规求余结果 58295
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为94674679062014814486157280995354483923643612065时-----------
快速幂取余结果 66453
常规求余结果 66453
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为946746790620148144861572809953544839236436120720时-----------
快速幂取余结果 69416
常规求余结果 69416
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为9467467906201481448615728099535448392364361207229时-----------
快速幂取余结果 21940
常规求余结果 21940
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为94674679062014814486157280995354483923643612072318时-----------
快速幂取余结果 73483
常规求余结果 73483
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为946746790620148144861572809953544839236436120723233时-----------
快速幂取余结果 36674
常规求余结果 36674
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为9467467906201481448615728099535448392364361207232425时-----------
快速幂取余结果 55592
常规求余结果 55592
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为94674679062014814486157280995354483923643612072324321时-----------
快速幂取余结果 9412
常规求余结果 9412
快速求余耗时: 0.0 欧拉求余耗时 0.0
-----------当b为946746790620148144861572809953544839236436120723243266时-----------
快速幂取余结果 41483
常规求余结果 41483
快速求余耗时: 0.0009987354278564453 欧拉求余耗时 0.0