[数学记录]CF923E Perpetual Subtraction
command_block · · 个人记录
填坑。去年省选就看到学长做这题了。
题意 : 有一个
然后进行
设当前这个数为
问操作后其分布的概率生成函数。
我们设
我们考虑一次操作之后会有何影响 :
将
这里是积分到
对积分也进行位移:
现在我们的
我们观察系数,有powM就好了。
问题在于怎么得到
设
众所周知二项式反演能够NTT,现在我们能在
#include<algorithm>
#include<cstdio>
#define ll long long
#define mod 998244353
#define G 3
#define Maxn 135000
using namespace std;
inline int read()
{
register int X=0;
register char ch=0;
while(ch<48||ch>57)ch=getchar();
while(ch>=48&&ch<=57)X=X*10+(ch^48),ch=getchar();
return X;
}
ll powM(ll a,int t=mod-2)
{
ll ans=1;
while(t){
if(t&1)ans=ans*a%mod;
a=a*a%mod;
t>>=1;
}return ans;
}
int r[Maxn<<2];
ll invG=powM(G),fac[Maxn],inv[Maxn];
void NTT(ll *f,bool op,int n)
{
for (int i=0;i<n;i++)
if (r[i]<i)swap(f[r[i]],f[i]);
for (int len=1;len<n;len<<=1){
int w=powM(op==1 ? G:invG,(mod-1)/len/2);
for (int p=0;p<n;p+=len+len){
ll buf=1;
for (int i=p;i<p+len;i++){
int sav=f[i+len]*buf%mod;
f[i+len]=f[i]-sav;
if (f[i+len]<0)f[i+len]+=mod;
f[i]=f[i]+sav;
if (f[i]>=mod)f[i]-=mod;
buf=buf*w%mod;
}
}
}
}
ll g[Maxn<<1];
void times(ll *f,ll *gg,int len,int lim)
{
int m=len+len,n;
for(int i=0;i<len;i++)g[i]=gg[i];
for(n=1;n<m;n<<=1);
for(int i=len;i<n;i++)g[i]=0;
for(int i=0;i<n;i++)
r[i]=(r[i>>1]>>1)|((i&1)?n>>1:0);
NTT(f,1,n);NTT(g,1,n);
for(int i=0;i<n;++i)f[i]=f[i]*g[i]%mod;
NTT(f,0,n);ll invn=powM(n);
for(int i=0;i<lim;++i)f[i]=f[i]*invn%mod;
for(int i=lim;i<n;++i)f[i]=0;
}
ll f[Maxn<<1],p[Maxn<<1],m;
int n;
int main()
{
n=read()+1;
scanf("%I64d",&m);m%=(mod-1);
fac[0]=1;
for (int i=1;i<=n;i++)fac[i]=fac[i-1]*i%mod;
inv[n]=powM(fac[n]);
for (int i=n;i;i--)inv[i-1]=inv[i]*i%mod;
for (int i=0;i<n;i++)f[i]=read();
for (int i=0;i<n;i++)p[n-i-1]=f[i]*fac[i]%mod;
for (int i=0;i<n;i++)f[i]=inv[i]%mod;
times(p,f,n,n);
for (int i=0;i<n;i++)f[n-i-1]=p[i]*inv[n-i-1]%mod;
for (int i=0;i<n;i++)f[i]=f[i]*powM(i+1,mod-1-m)%mod;
for (int i=0;i<n;i++)
if (i&1)p[n-i-1]=mod-(f[i]*fac[i]%mod);
else p[n-i-1]=f[i]*fac[i]%mod;
for (int i=0;i<n;i++)f[i]=inv[i]%mod;
times(p,f,n,n);
for (int i=0;i<n;i++)f[n-i-1]=p[i]*inv[n-i-1]%mod;
for (int i=0;i<n;i++)
printf("%I64d ",(i&1) ? (mod-f[i])%mod : f[i]);
puts("");return 0;
}