逆元板子集

其实就是怕忘了……这里发一下线性求逆元以及阶乘的逆元的板子。

 

线性求逆元

逆元是啥我就不说了,但是线性递推式怎么来的我还是可以证明一下的。

 

求 i 的逆元,假设[1, i - 1]的逆元已知。

设 p = k * i + b,则 b = p % i, k = ⌊p / i⌋ 。

则k * i + b Ξ 0 (mod p),所以b Ξ - k * i。

两边同乘inv[b]得:inv[b] * b Ξ - k * i * inv[b] (mod p)

化简得:    - k * i * inv[b] Ξ 1 (mod p)

两边同乘inv[i]得:inv[i] Ξ - k *inv[b] (mod p)

        inv[i] Ξ (p - k) * inv[b]

        inv[i] Ξ (p - ⌊p / i⌋) * inv[p % i]

所以      inv[i] = (p - ⌊p / i⌋) * inv[p %i] % p

装模作样来个代码。

1 inv[1] = 1;
2 for(int i = 2; i <= n; ++i) inv[i] = inv[mod % i] * (mod - mod / i) % mod;

 

 

线性求阶乘的逆元

其实就是根据inv[i] = inv[i + 1] * (i + 1) % p倒着递推而来。

先用费马小定理求出inv[n]的逆元,然后倒着递推。

 1 ll quickpow(ll a, ll b)
 2 {
 3     a %= mod;
 4     ll ret = 1;
 5     for(; b; b >>= 1, a = a * a % mod) 
 6         if(b & 1) ret = ret * a % mod;
 7     return ret;
 8 }
 9 ll fac[maxn], inv[maxn];
10 void init(int n)
11 {
12     fac[1] = 1;
13     for(int i = 2; i <= n; ++i) fac[i] = fac[i - 1] * i % mod;
14     inv[n] = quickpow(fac[n], mod - 2);
15     for(int i = n - 1; i; --i) inv[i] = inv[i + 1] * (i + 1) % mod;
16 }

 

posted @ 2018-10-22 23:10  mrclr  阅读(216)  评论(0编辑  收藏  举报