\((a\times b)\bmod p\),\(a,b<p\leq 10^{18}\)
不说龟速乘了。
\[(a\times b)\bmod p=a\times b-\left\lfloor\frac {a\times b}{p}\right\rfloor\times p=\left(a\times b-\left\lfloor\frac {a\times b}{p}\right\rfloor\times p\right)\bmod 2^{64} \]关键在于算 \((\lfloor\frac {a\times b}{p}\rfloor)\bmod 2^{64}\)
考虑用 long double 算出 \(\dfrac ap\times b\)
考虑精度误差,\(\dfrac ap\in [0,1)\),因此所以有位都用于保存小数位,精度误差为 \((-2^{-64},2^{-64})\),乘 \(b\) 后误差最多为 \((-0.5,0.5)\),加上 \(0.5\) 后为 \((0,1)\),取整后为 \(\{0,1\}\),再乘上 \(-p\),误差为 \(\{0,-p\}\)。注意到如果误差为 \(-p\),那么结果将为负,取模后是一个极大的值,所以只需判断结果是否在 \([0,p)\) 中即可确定误差。
ull mul(ull a, ull b, ull p){
ull res=a*b-(ull)((long double)a/p*b+0.5L)*p;
if(res<p) return res;
else return res+p;
}
标签:取模,误差,bmod,0.5,times,64,ull,乘法
From: https://www.cnblogs.com/pref-ctrl27/p/17094763.html