先引入一个相关问题:
如何快速求解$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;
}
```