转载于CSDNLiiiiiiiiiiiiiiiiiiq大佬,原地址:https://blog.csdn.net/qq_36760780/article/details/80092665?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param
今天在网上看了一些快速幂取模算法的介绍,总体感觉要么文章介绍的很简略,导致我搞了半天才搞明白什么意思,还有的文章直接放上了错误的代码,真是坑爹啊!所以我就特意写一篇文章方便大家理解一下这个算法的原理和代码是什么意思。
原理介绍:
目标:快速求出 ab Mod c (注意:b是一个大数)
数学原理工具: (a*b) Mod c = [(a Mod c)*(b Mod c)] Mod c (加上括号是为了方便理解运算顺序,证明不难,可以自己百度)
考虑到b是一个大数,直接算 ab 会很慢,所以首先把 b 转换成二进制形式(这个转换不用再写一个程序,计算机里面就是二进制保持的)
b=(bnbn-1bn-2…b3b2b1b0)2
b=b0 + b1*21 + b2*22 + b3*23 + b4*24 +…+ bn-1*2n-1 + bn*2n
ab = ab0+b1*2^1 + b2*2^2+ b3*2^3 + b4*2^4 +…+ bn-1*2^(n-1) + bn*2^n
= ab0 * ab1*2^1 * ab2*2^2 * ab3*2^3 *…* abn*2^n
ab % c = (ab0*ab1*2^1*ab2*2^2*ab3*2^3*…*abn*2^n) % c
设 An=(ab0*ab1*2^1*ab2*2^2*ab3*2^3*…*abn*2^n) % c
考虑到 (a*b) Mod c = [(a Mod c)*(b Mod c)] Mod c
An=[(ab0*ab1*2^1*ab2*2^2*…*ab(n-1)*2^(n-1))%c*(abn*2^n)%c]%c
=[ An-1* (abn*2^n) % c ] % c
为了方便这里设 Kn=(abn*2^n) % c 于是我们就得到一个递推关系
An = (An-1*Kn) % c
A0 = ab0 % c
这里有一个问题就是Kn怎么求,考虑到Kn和bn有关,当bn取0时,Kn=1.当bn取1时,Kn = (a2^n) % c 所以关键是计算 (a2^n) % c 的值, 可以发现
(a2^n) % c = ( a2^(n-1)* a2^(n-1))% c
= [ (a2^n-1) % c * (a2^n-1) % c ] % c
所以可以设 Tn= (a2^n) % c 那么可以得到
Tn= (a2^n) % c
= ( a2^(n-1)* a2^(n-1))% c
= [(a2^n-1) % c * (a2^n-1) % c ] % c
= ( Tn-1 * Tn-1 ) % c
得到以下递推关系
Tn=( Tn-1 * Tn-1 ) % c
T0= a % c
现在总结以下,首先我们的目标是求出An,我们已经得到递推关系,但是在递推过程中我们还要Kn,所以我们得计算Kn,而Kn和bn有关,当bn=0,Kn=1,当bn=1,Kn=Tn,考虑到我们可能在任何地方需要Tn,因为b的二进制的1的位置是都有可能的,所以我们需要一直计算Tn,就是说当bn=0时我们也是要计算Tn的,因为可能以后会用到,而求Tn我们也已经给出了递推式,所以问题可以解决了。下面看一下代码