求一個底數的高次冪取模(a^b%c)時我們會用到快速冪取模,其時間復雜度為logN。
然而當兩個大數進行相乘進行取模(a*b%c)時,運算a*b可能會爆long long的范圍,如果會python的同學做這種題目的時候或許不用為此困擾,然而博主這樣不會python的蒟蒻該如何應對這種兩數相乘會爆范圍的情形呢?這時候就需要用到 快速乘 啦!
進入正題:
0.為什么快速乘不會爆范圍,原因如下:
乘法容易爆范圍,但是由於過程中不斷取模,所以加法不會爆范圍。
1.如何用加法實現快速乘?原理如下:
快速乘是利用乘法分配律將a*b分解成多個式子相加(將后面一個乘數轉化為二進制的形式計算)求解。例如:12*11=12*1011(2)=12*2^3+12*2^1+12*2^0=96+24+12=132
2.代碼實現:
1 typedef long long LL; 2 LL mult_mod(LL a,LL b,LL mod) 3 { 4 LL res=0; //注意此處初始化為0不是1 5 while(b){ 6 if(b&1)res=(res+a)%mod; 7 a=(a+a)%mod; //注意此處是加不是乘 8 b/=2; 9 } 10 return res; 11 }
3.補充說明:
按位與運算(&)
按位與運算符"&"是雙目運算符。 其功能是參與運算的兩數各對應的二進位相與。只有對應的兩個二進位均為1時,結果位才為1 ,否則為0。參與運算的數以補碼方式出現。
4.快速冪與快速乘的綜合運用:
1 #include<stdio.h> 2 typedef long long LL; 3 LL mult_mod(LL a,LL b,LL c) //快速乘 4 { 5 LL res=0; 6 while(b){ 7 if(b&1)res=(res+a)%c; 8 a=(a+a)%c; 9 b=b/2; 10 } 11 return res; 12 } 13 LL pow_mod(LL a,LL b,LL mod) //快速冪 14 { 15 LL res=1; 16 while(b){ 17 if(b&1)res=mult_mod(res,a,mod); 18 res%=mod; 19 a=mult_mod(a,a,mod); 20 a%=mod; 21 b=b/2; 22 } 23 return res; 24 } 25 int main() 26 { 27 LL a,b,mod,sum; 28 scanf("%lld%lld%lld",&a,&b,&mod); 29 sum=pow_mod(a,b,mod); 30 printf("%lld\n",sum); 31 return 0; 32 }
謝謝觀看,如有問題歡迎提出並指正。