Barrett Reduction

巴雷特约减

不知道为什么突然想写这个。

由于朴素的取模效率过于低下,所以上 Barrett Reduction 可以在一定程度上减小常数。

容易注意到 $ x \mod M = x - \lfloor \frac{x}{M} \rfloor \times M $ 。但直接这样做仍然很慢,因为用到了除法运算。

我们知道除以 $ 2^k $ 是可以用位运算做到很快的,考虑使用右移估算除法。

\[\lfloor \frac{x}{M} \rfloor \approx \lfloor \frac{ x \times \lfloor \frac{ 2^N }{M} \rfloor }{ 2^N } \rfloor \]

设 $ 2^N = k\times M +r , ( 0 \le r < M ) $ ,那么有 $ \lfloor \frac{x}{M} \rfloor = \lfloor \frac{ x k }{ 2^N - r } \rfloor $ , $ \lfloor \frac{ x \times \lfloor \frac{ 2^N }{M} \rfloor }{ 2^N } \rfloor = \lfloor \frac{ x k }{ 2^N } \rfloor $ 。

这样一定正确吗?其实不一定,有极小错误的概率。

一般的编译器如果对一个常量取模会自动上 Barrett Reduction ,手动优化并不是很明显。但亲测确实对卡常有帮助,效果可能和编译器有关。

CODE
struct Mod{
	ll m,p;
	void init(int pp){m=((__int128)1<<64)/pp; p=pp;}
	ll operator () (ll x){
		return x-((__int128(x)*m)>>64)*p;
	}
}MOD;
posted @ 2025-07-05 22:15  Abnormal123  阅读(24)  评论(0)    收藏  举报