一、什么是快速乘法?
快速乘主要是解决乘法可能会爆的情况,快速乘原理就是利用了乘法分配来将ab转化为多个式子相加的形式求解。
当两个大数进行相乘进行取模(a*b%c)时,运算a*b可能会爆long long的范围,这时候就需要用到 快速乘 算法解决算术溢出的问题。
1.乘法容易爆范围,但是由于过程中不断取模,所以加法不会爆范围。
2.在计算机中,加法比乘法计算速度快;快速乘算法的本质是把乘法分解为加法,所以计算速度更快。
二、快速乘法的推演过程
举个案例:求9*14%5的结果
一般思路:
9*14%5
=76%5
=1
快速乘法:
9*14%5
=9*(1110)%5
=9*(2^3+2^2+2^1)%5
=9*(8+4+2)%5
=(72+36+18)%5
=(72%5+36%5+18%5)%5
=(2+1+3)%5
=1
可以发现快速乘法避开了两个数据直接相乘的过程。
1)复杂度O(logn)的快速乘
typedef long long LL;
LL mult_mod(LL x,LL y,LL mod){//计算x乘y的积
LL res=0;
while(y){
if(y&1) res=(res+x)%mod;
x=(x<<1)%mod;
y>>=1;
}
return res;
}
2)复杂度O(1)的快速乘
typedef long long LL;
typedef long double LD;
typedef unsigned long long ULL;
LL mult_mod(LL x,LL y,LL mod){ // 一种自动溢出的数据类型(存满了就会自动变为0)
LL z=(LD)x/mod*y;
LL res=(ULL)x*y-(ULL)z*mod;
return (res+p)%mod;
}
三、再来聊聊快速幂
案例:求9^3%5的结果
一般思路:
先求9的3次幂结果: 729
然后 %5:4
最终结果:4
typedef long long LL;
LL pow_mod(LL x,LL y,LL mod){
LL res=1;
while(y--)
res*=x%mod;
return res;
}
快速幂法:
9^3%5
=9^(11)%5
=9^(2^1+2^0)%5
=((9^2%5)*(9^1%5))%5
=(1*4)%5
=4
一般快速幂:
typedef long long LL;
LL pow_mod(LL x,LL y,LL mod){
LL res=1;
while(y!=0){
if(y%2) res=(res*x)%mod;
x=(x*x)%mod;
y/=2;//或者y>>1;
}
return res%mod;
}
快速幂(递归)
typedef long long LL
LL pow_mod(LL x,LL y,LL mod){
if(y==1) return x%mod;
LL res=pow_mod(x,y/2)%mod;
return (y%2==0 ? 1 : x)*(res*res)%mod;
}
快速幂(位运算)
typedef long long LL
LL pow_mod(LL x, LL y,LL mod){
LL res = 1;
while(y != 0){
if(y&1) res= (res*x)%mod;
x=(x*x)%mod;
y>>=1;
}
return res;
}
四、总结
中心思想还是基于数据存储在计算机中的形式是二进制0和1,以及折半思想等