快速乘

两个数直接乘爆 ( ext{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} floor imes mod) 就是巧妙的把溢出的减掉了感性理解, 使答案在 ( ext{long long}) 范围内


假如怕有精度误差的话其实可以使用 ( ext{__int128}) 来实现 (O(1)) 快速乘 (实测比 ( ext{long double}) 慢)

LL fastMulMod(LL x, LL y, LL mod) {
	return static_cast<__int128>(1) * x * y % mod;
}

( ext{__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;
	}
}

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

原文地址:https://www.cnblogs.com/Lskkkno1/p/12165565.html