写在前面
快速乘其实跟快速幂很像,思想都是差不多的。
快速幂
价值:
乘法都是
O
(
1
)
O(1)
O(1)的,那要快速乘做甚么?
一旦数变大(像long long),并且连
m
o
d
mod
mod数都是
l
o
n
g
long
long
l
o
n
g
long
long级别的,那必然会爆。高精度,又难打又慢,许多题目本来就卡常,打来必是白给。
于是,快速乘应运而生。
思想
小学有讲,四则运算加乘法的关系就是
X
∗
Y
=
X
+
X
+
X
+
X
X*Y=X+X+X+X
X∗Y=X+X+X+X
(
Y
(Y
(Y个
)
)
)
所以如果能够把乘法转换为加法,一点点mod就基本爆不了。
但如果直接加,那时间复杂度就是
O
(
Y
)
O(Y)
O(Y),很明显不能接受。
所以考虑借鉴快速幂思想。
分析
首先我们知道一个数必然能分解为
2
0
+
2
1
+
2
3
2^0+2^1+2^3
20+21+23……这样幂的形式。 随机抽取一位幸运数字:
58
58
58
它就等于
32
+
16
+
8
+
2
(
2
5
+
2
4
+
2
3
+
2
1
)
32+16+8+2(2^5+2^4+2^3+2^1)
32+16+8+2(25+24+23+21)
假设我们要算
58
58
58乘
6
6
6
根据乘法分配律
58
∗
6
=
(
2
5
+
2
4
+
2
3
+
2
1
)
∗
6
=
2
5
∗
6
+
2
4
∗
6
+
2
3
∗
6
+
2
1
∗
6
58*6=(2^5+2^4+2^3+2^1)*6=2^5*6+2^4*6+2^3*6+2^1*6
58∗6=(25+24+23+21)∗6=25∗6+24∗6+23∗6+21∗6
那么如何模拟这一操作,其实也很简单:
暂时设要求
X
∗
Y
X*Y
X∗Y
X
X
X每次都乘
2
2
2,(即转换为
2
n
∗
X
2^n*X
2n∗X)如果这一位(二进制下)有
1
1
1,则加入
a
n
s
ans
ans
如何判断该位有
1
1
1?只需
Y
m
o
d
2
Y mod 2
Ymod2,判断是否有余数
然后每次Y除以2,即在二进制下右移一位
代码(协助理解)
long long quick_mult(long long x,long long y)
{
long long ans=0;
while(y)//还没加分解彻底
{
if (y&1) ans=ans+x%p;//y&1意思就是y%2,如果该位有值则加入ans
x=x<<1%p;//x乘2进位
y>>=1;//y在二进制下右移一位
}
return ans;
}
留言,见必回。