【2020-2021集训队作业】春天,在积雪下结一成形,抽枝发芽
【2020-2021集训队作业】春天,在积雪下结一成形,抽枝发芽
Description
计数不存在非平凡(长为\(1\)或\(n\))连续段使得其值域也是连续的的\(n\)阶排列个数
模\(998244353\)
Input
一行两个数\(ty,n\)
Output
\(ty=0\)时输出\(n\)的答案
\(ty=1\)时输出\(1\sim n\)的答案
Sample Input
1 4
Sample Output
1
2
0
2
Data Constraint
\(1\le n\le 10^5\)
Solution
不妨先考虑合点的情况
设排列的OGF为\(H(x)\),根为合点的OGF为\(G(x)\)
显然合点可以用\(n!\)减去只有一个儿子的情况
那么
\[G(x)=\sum_{i\ge 2}(H-G)^i=\frac{H^2}{1+H}
\]
然后考虑根为析点的情况
设\(F(x)\)为答案
那么由于任意大于\(1\)的段都不合法,所以析点可以用复合来表示
即
\[\sum_{i\ge 4}f_iH(x)^i=F(H(x))
\]
然后有
\[F(H(x))+2G+x=H(x)
\]
考虑\(H(x)\)的复合逆\(P(x)\)
那么
\[F(x)=x-\frac{2x^2}{1+x}-P(x)
\]
\(H(x)\)的ODE比较经典,然后结合\(H(P)'=x'=1=H'(P)P'\),就得到了
\[P^2+(x+1)PP'-xP'=0
\]
半在线卷积就行了
Code
#include<bits/stdc++.h>
using namespace std;
#define F(i,a,b) for(int i=a;i<=b;i++)
#define Fd(i,a,b) for(int i=a;i>=b;i--)
#define N 600010
#define mo 998244353
#define LL long long
#define ULL unsigned long long
int rev[N],G1[N],G2[N],fac[N],ifac[N],inv[N];
int mod(int x){return x>=mo?x-mo:x;}
int mi(int x,int y){
if(!y)return 1;
if(y==1)return x;
return y%2?1ll*x*mi(1ll*x*x%mo,y/2)%mo:mi(1ll*x*x%mo,y/2);
}
void init(){
fac[0]=ifac[0]=1;
F(i,1,N-10)fac[i]=1ll*fac[i-1]*i%mo,inv[i]=(i==1?1:1ll*mo/i*mod(mo-1ll*inv[mo%i]%mo)%mo);
ifac[N-10]=mi(fac[N-10],mo-2);
Fd(i,N-11,1)ifac[i]=1ll*ifac[i+1]*(i+1)%mo;
for(int l=1;l<=N-10;l<<=1)G1[l]=mi(3,(mo-1)/(l*2)),G2[l]=mi(G1[l],mo-2);
}
void BRT(int x){F(i,0,x-1)rev[i]=(rev[i>>1]>>1)|((i&1)?(x>>1):0);}
struct poly{
vector<int>val;
poly(int x=0){if(x)val.push_back(x);}
poly(const vector<int>&x){val=x;}
void ins(int x){val.push_back(x);}
void clear(){vector<int>().swap(val);}
int sz(){return val.size();}
void rsz(int x){val.resize(x);}
void shrink(){for(;sz()&&!val.back();val.pop_back());}
void Rev(){reverse(val.begin(),val.end());}
poly modxn(int x){
if(val.size()<=x)return poly(val);
else return poly(vector<int>(val.begin(),val.begin()+x));
}
int operator[](int x)const{
if(x<0||x>=val.size())return 0;
return val[x];
}
void NTT(int x){
static ULL f[N],w[N];
w[0]=1;
F(i,0,sz()-1)f[i]=(((LL)mo<<5)+val[rev[i]])%mo;
for(int mid=1;mid<sz();mid<<=1){
int tmp=(x==1?G1[mid]:G2[mid]);
F(i,1,mid-1)w[i]=w[i-1]*tmp%mo;
for(int i=0;i<sz();i+=(mid<<1)){
F(j,0,mid-1){
int t=w[j]*f[i|j|mid]%mo;
f[i|j|mid]=f[i|j]+mo-t;f[i|j]+=t;
}
}
//if(mid==(1<<10)){F(i,0,sz()-1)f[i]%=mo;};
}
if(x==-1){int tmp=inv[sz()];F(i,0,sz()-1)val[i]=f[i]%mo*tmp%mo;}
else{F(i,0,sz()-1)val[i]=f[i]%mo;}
}
void DFT(){NTT(1);}
void IDFT(){NTT(-1);}
friend poly operator*(poly x,poly y){
if(x.sz()<30||y.sz()<30){
if(x.sz()>y.sz())swap(x,y);
poly ret;
ret.rsz(x.sz()+y.sz());
F(i,0,ret.sz()-1){
for(int j=0;j<=i&&j<x.sz();j++)
ret.val[i]=mod(ret.val[i]+1ll*x[j]*y[i-j]%mo);
}
// ret.shrink();
return ret;
}
int l=1;
while(l<x.sz()+y.sz()-1)l<<=1;
x.rsz(l);y.rsz(l);BRT(l);
x.DFT();y.DFT();
F(i,0,l-1)x.val[i]=1ll*x[i]*y[i]%mo;
x.IDFT();
// x.shrink();
return x;
}
friend poly operator+(poly x,poly y){
poly ret;
ret.rsz(max(x.sz(),y.sz()));
F(i,0,ret.sz()-1)ret.val[i]=mod(x[i]+y[i]);
return ret;
}
friend poly operator-(poly x,poly y){
poly ret;
ret.rsz(max(x.sz(),y.sz()));
F(i,0,ret.sz()-1)ret.val[i]=mod(x[i]-y[i]+mo);
return ret;
}
poly &operator*=(poly x){return (*this)=(*this)*x;}
poly &operator+=(poly x){return (*this)=(*this)+x;}
poly &operator-=(poly x){return (*this)=(*this)-x;}
poly deriv(){
poly f;
f.rsz(sz()-1);
F(i,0,sz()-2)f.val[i]=1ll*(i+1)*val[i+1]%mo;
return f;
}
poly integ(){
poly f;
f.rsz(sz()+1);
F(i,1,sz())f.val[i]=1ll*val[i-1]*inv[i]%mo;
return f;
}
poly inver(int Len){
poly f,g,res(mi(val[0],mo-2));
for(int i=1;i<Len;){
i<<=1;f.rsz(i);g.rsz(i);BRT(i);
F(j,0,i-1)f.val[j]=(*this)[j],g.val[j]=res[j];
f.DFT();g.DFT();
F(j,0,i-1)f.val[j]=1ll*f[j]*g[j]%mo;
f.IDFT();
F(j,0,(i>>1)-1)f.val[j]=0;
f.DFT();
F(j,0,i-1)f.val[j]=1ll*f[j]*g[j]%mo;
f.IDFT();
res.rsz(i);
F(j,i>>1,i-1)res.val[j]=mod(mo-f[j]);
}
return res.modxn(Len);
}
poly Sqrt(int Len){
int i2=inv[2];
poly f,g,tmp;
f.clear();g.clear();
g.ins(1);
for(int i=1;i<Len*2;i<<=1){
int Len=i<<1;
f.rsz(Len);
tmp=g.inver(i);
tmp.rsz(Len);
BRT(Len);
F(j,0,i-1)f.val[j]=(j<val.size()?val[j]:0);
f.DFT();tmp.DFT();
F(j,0,Len-1)f.val[j]=1ll*f[j]*tmp[j]%mo;
f.IDFT();
g.rsz(i);
F(j,0,i-1)g.val[j]=1ll*i2*mod(g[j]+f[j])%mo;
}
return g.modxn(Len);
}
poly Ln(int Len){
return (deriv()*inver(Len)).integ().modxn(Len);
}
poly Exp(int Len){
poly f;
f.clear();
f.ins(1);
for(int i=2;i<Len*2;i<<=1)f=(f*(1-f.Ln(i)+modxn(i))).modxn(i);
return f.modxn(Len);
}
poly Pow(int Len,int k){
poly f;
f.clear();
int tail=0;
while(val[tail]==0&&tail<sz())tail++;
if(tail>=sz())return f;
if(tail*k>=Len)return f;
f.rsz(Len);
int Mul=mi(val[tail],mo-2);
F(i,0,min(Len-1,sz()-tail-1))f.val[i]=1ll*val[i+tail]*Mul%mo;
Mul=mi(val[tail],k);
f=f.Ln(Len);
F(i,0,Len-1)f.val[i]=1ll*f[i]*(k%mo)%mo;
f=f.Exp(Len);
Fd(i,Len-1,tail*k)f.val[i]=1ll*f[i-tail*k]*Mul%mo;
F(i,0,tail*k-1)f.val[i]=0;
return f;
}
};
int ty,n;
poly f;
void solve(int l,int r){
if(l==r)return;
int mid=l+r>>1;
poly p,q;
if(l==1){
solve(l,mid);
p.clear();q.clear();
F(i,0,mid)p.ins(1ll*(i+1)*f[i]%mo);
F(i,0,mid)q.ins(f[i]);
p*=q;
F(i,mid+1,r)f.val[i]=mod(f[i]-p[i]+mo);
p.clear();q.clear();
F(i,0,mid)p.ins(1ll*i*f[i]%mo);
F(i,0,mid)q.ins(f[i]);
p*=q;
F(i,mid+1,r)f.val[i]=mod(f[i]-p[i+1]+mo);
solve(mid+1,r);
}else{
solve(l,mid);
p.clear();q.clear();
F(i,l,mid)p.ins(1ll*(i+1)*f[i]%mo);
F(i,0,r-l)q.ins(f[i]);
p*=q;
F(i,mid+1,r)f.val[i]=mod(f[i]-p[i-l]+mo);
p.clear();q.clear();
F(i,l,mid)p.ins(1ll*i*f[i]%mo);
F(i,0,r-l+1)q.ins(f[i]);
p*=q;
F(i,mid+1,r)f.val[i]=mod(f[i]-p[i-l+1]+mo);
p.clear();q.clear();
F(i,0,r-l)p.ins(1ll*(i+1)*f[i]%mo);
F(i,l,mid)q.ins(f[i]);
p*=q;
F(i,mid+1,r)f.val[i]=mod(f[i]-p[i-l]+mo);
p.clear();q.clear();
F(i,0,r-l+1)p.ins(1ll*i*f[i]%mo);
F(i,l,mid)q.ins(f[i]);
p*=q;
F(i,mid+1,r)f.val[i]=mod(f[i]-p[i-l+1]+mo);
solve(mid+1,r);
}
}
int main(){
init();
scanf("%d%d",&ty,&n);
f.rsz(n+1);
f.val[1]=1;
solve(1,n);
f.val[1]=1;f.val[2]=2;
F(i,3,n){
f.val[i]=mod(mo-f[i]);
f.val[i]=mod(f[i]+(i&1?2:mo-2));
}
if(!ty){printf("%d",f[n]);return 0;}
F(i,1,n)printf("%d\n",f[i]);
return 0;
}