线性预处理逆元

求 1..n 之间每个数的逆元,如果都用费马小定理或者扩展欧几里得算,那么复杂度将会达到 $O(n \log p)$ 。利用一些递推式,可以线性地求出1..n中每个数的逆元,从而复杂度可以减少一个log。常用的一个递推公式是

$$i^{-1} = -\left\lfloor \frac{p}{i} \right\rfloor \cdot (p \bmod i)^{-1} \bmod p$$

这一公式的正确性也很好证明,等式右端可以写成(模p意义下)

$$-\frac{\left\lfloor \frac{p}{i} \right\rfloor}{p-\left\lfloor \frac{p}{i} \right\rfloor i} = \frac{1}{i}$$

利用此公式我们可以在 $O(n)$ 时间内求出1..n中每个数的逆元。

void init_inv()
{
    inv[1] = 1;
    for(int i = 2;i < n;i++)  inv[i] = (mod -  mod / i) * inv[mod % i] % mod;  //加mod不改变结果
}

 

 

参考链接:http://aequa.me/index.php/tag/lagrange-interpolation/

 

posted @ 2019-07-15 14:58  Rogn  阅读(1409)  评论(0编辑  收藏  举报