题解 P3811 【【模板】乘法逆元】

Ireliaღ

2019-07-24 13:07:34

Solution

## 这是一种不一样的线性逆元递推求法 ~~其实也可以线性求出来任意一坨相乘得到的数的逆元~~ ### 思路 根据逆元的意义,我们容易知道,如果我们知道$(xy)^{-1}(mod p)$,那么我们乘以$y$,就可以$O(1)$得到$x^{-1} (modp)$。 这样,$x$的逆元,可以利用$(x!)^{-1} \times (x - 1)!$这个式子求出来。所以,我们可以先递推出$n!$,然后用扩欧或者快速幂求出$(n!)^{-1}(modp)$,就可以反过来递推出$1$到$n$的所有逆元 ### 代码 `cout`会超时,因为取消流同步和绑定只能加速`cin` ```cpp // luogu-judger-enable-o2 #include <iostream> using namespace std; const int MAXN = 3e6 + 5; int fac[MAXN], inv[MAXN], n, p; int Exgcd(int a, int b, int &x, int &y) { if (b == 0) { x = 1; y = 0; return a; } int ret = Exgcd(b, a % b, y, x); y -= 1LL * a / b * x; return ret; } void GetInv(int x, int finv, int mod) { if (x == 0) return; int ninv = 1LL * finv * fac[x - 1] % mod; GetInv(x - 1, 1LL * finv * x % mod, mod); //cout << ninv << endl; printf("%d\n", ninv); } int main() { //ios :: sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); cin >> n >> p; fac[0] = 1; for (int i = 1; i <= n; i++) fac[i] = 1LL * fac[i - 1] * i % p; int x, y; Exgcd(fac[n], p, x, y); GetInv(n, (x + p) % p, p); return 0; } ```