求一个底数的高次幂取模(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 }
谢谢观看,如有问题欢迎提出并指正。