线性预处理逆元

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

$$i^{-1} = -leftlfloor frac{p}{i} ight floor cdot (p mod i)^{-1} mod p$$

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

$$-frac{leftlfloor frac{p}{i} ight floor}{p-leftlfloor frac{p}{i} ight floor 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/

原文地址:https://www.cnblogs.com/lfri/p/11188923.html