# 快速乘
ps : 建議先去看[快速冪](/OBXWeBUOTH-Eo5FIcMIHDA),方法跟快速冪類似
如果要把兩個很大的數相乘且mod M,很有可能會溢位,那就要利用快速乘了
### 快速乘 : 把兩個數的乘法轉換成加法
題目:
```cpp=
(A×B)%M
```
把B轉乘二進制
假設B=14<sub>10</sub>=(1110)<sub>2</sub>= (2^3^)×1 + (2^2^)×1 + (2^1^)×1 + (2^0^)×0
帶入題目
A×((2^3^)×1 + (2^2^)×1 + (2^1^)×1 + (2^0^)×0)
= A×(2^3^)×1 + A×(2^2^)×1 + A×(2^1^)×1 + A×(2^0^)×0
= (2^3^×A)×1 + (2^2^×A)×1 + (2^1^×A)×1 + (2^0^×A)×0
### 從後面開始運算,由右往左,每次B>>=1 , a+=a
由A前面的係數可知,每次都多乘2,所以每次的運算都是A*=2
每個元素最後面的0或1決定此元素是否有效,也就是說,如果是0就不用裡他,是1再把前面的數加到答案裡,此0跟1可由B&1得到
```cpp=
int mul(int a,int b){
int ans=0;
while(b!=0){
if(b & 1){
ans+=a;
}
b/=2;
a*=2;
}
return ans;
}
```
改成位元運算
```cpp=
int mul(int a,int b,int m){
int ans=0;
while(b){
if(b & 1){
ans+=a;
}
b>>=1;
a<<=1;
}
return ans;
}
```
取模
```cpp=
int mul(int a,int b,int m){
a%=m;b%=m;
int ans=0;
while(b){
if(b & 1){
ans=(ans+a)%m;
}
b>>=1;
a=(a<<1)%m;
}
return ans;
}
```
例題 : <a href="https://zerojudge.tw/ShowProblem?problemid=b430">b430: 簡單乘法</a>
```cpp=
#include <bits/stdc++.h>
#define int long long
using namespace std;
int mul(int a,int b,int m){
a%=m;b%=m;
int ans=0;
while(b){
if(b & 1){
ans=(ans+a)%m;
}
b>>=1;
a=(a<<1)%m;
}
return ans;
}
signed main(){
cin.sync_with_stdio(0),cin.tie(0);
int a,n,b;
while(cin >> a >> b >> n){
cout << mul(a,b,n) << '\n';
}
return 0;
}
```