快速乘
两个数直接乘爆 \(\text{long long}\) 怎么办 ?
使用快速乘
先来个 \(O(1)\) 快速乘
LL fastMulMod(LL x, LL y, LL mod) {
return (x * y - (LL)((long double)x * y / mod) * mod + mod) % mod;
}
首先假如不会溢出的话, 后面两项都被模掉了就只剩 x * y
了对吧
后面的 \(\lfloor \frac {xy} {mod}\rfloor \times mod\) 就是巧妙的把溢出的减掉了感性理解, 使答案在 \(\text{long long}\) 范围内
假如怕有精度误差的话其实可以使用 \(\text{__int128}\) 来实现 \(O(1)\) 快速乘 (实测比 \(\text{long double}\) 慢)
LL fastMulMod(LL x, LL y, LL mod) {
return static_cast<__int128>(1) * x * y % mod;
}
但 \(\text{__int128}\) 在联赛中并不能用, 那我就再贴个 \(O(logn)\) 快速乘, 也是最常见的快速乘
LL fastMulMod(LL x, LL y, LL mod) {
LL res = 0;
while(x) {
if(x & 1) res = (res + y) % mod;
y = (y << 1) % mod, x >>= 1;
}
}
本质上是运用了乘法分配率, 没什么好讲的