64 位整数乘法取模

\((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;
}
posted @ 2023-02-06 11:03  pref_ctrl27  阅读(51)  评论(0编辑  收藏  举报