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

redegg

2018-11-08 15:14:09

Solution

先引入一个相关问题: 如何快速求解$1$~$n$的阶乘逆元? 首先求出$n!$的逆元,$(n-1)!$的逆元是等于$n!$的逆元乘$n$。 设$P(x)$为$x$的逆元,可以这样简洁的证明: $P(n!)\times x=\frac{1}{n!} \times x$ $P(n!) \times n=\frac{1}{(n-1)!}$ 那么同理,我们可以求到$1$~$n$的所有数的阶乘的逆元。 ------------------------------------------- 好了相关问题结束。 那么我们知道了$n!$的逆元,我们怎么求$n$的逆元呢? 当然直接乘上$(n-1)!$就可以啦! 证明和上面差不多: $\frac{1}{n!}=P(n!)$ $\frac{1}{n!} \times (n-1)!=\frac{1}{n}=P(n)=P(n!)\times (n-1)!$ 综上:$P(n)=P(n!)\times (n-1)!$ $1$~$n$的阶乘可以预处理算出吧! $n!$的逆元可以一次快速幂求出吧! 最后从大到小用上面综上里的公式依次求出逆元,别忘了$\%p$。 代码如下: ```cpp #include <bits/stdc++.h> using namespace std; long long n; long long p; long long c[3000006]; long long fast(long long x,long long y) { long long an=1; while(y) { if(y&1) an=(an*x)%p; x=(x*x)%p; y>>=1; } return an; } long long ans[3000006]; int main() { scanf("%lld%lld",&n,&p); c[0]=1; for(long long i=1;i<=n;i++) c[i]=(c[i-1]*i)%p; long long last=fast(c[n],p-2); long long k; for(int i=n;i>=1;i--) { k=(last*i)%p; ans[i]=(last*c[i-1])%p; last=k; } for(int i=1;i<=n;i++) printf("%lld\n",ans[i]); return 0; } ```