快速乘

求一个底数的高次幂取模(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  }

 

 谢谢观看,如有问题欢迎提出并指正。

posted @ 2019-03-20 14:51  Maze_End  阅读(1533)  评论(0编辑  收藏  举报