快速乘

两个数直接乘爆 \(\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;
	}
}

本质上是运用了乘法分配率, 没什么好讲的

posted @ 2020-01-08 11:16  Lskkkno1  阅读(136)  评论(0编辑  收藏  举报