龟速乘(防止爆long long)
快速乘
在某些乘数特别大的情况,比如题目给定的模数大于 \(10^9\) ,在之后的乘法计算中可能会爆 \(long \ long\) ,可以使用 \(O(1)\) 快速乘在不爆 \(long \ long\) 的情况下算出取模后的值。
typedef long long ll;
inline ll mul(ll a,ll b,ll mod){
return (a*b-(ll)((long double)a/mod*b)*mod+mod)%mod;
}
龟速乘
更多情况下,如果模数稍微比 \(10^9\) 大,如 \(2 * 10 ^ 9\),同样会爆long long,这时候可以使用龟速乘,也就是把 \(b\) 拆分成二进制,一边加一边取模。
typedef long long ll;
ll mul (ll a, ll b, ll mod) { // 防止爆long long
if(b < 0) a = -a, b = -b;
ll s = 0;
for (; b; b >>= 1, a = (a + a) % mod)
if (b & 1) s = (s + a) % mod;
return s;
}