轉載於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我們也已經給出了遞推式,所以問題可以解決了。下面看一下代碼