qczrz6v4nhp6u
2025-01-07 08:13:41
考虑 dp。设
做完上述转移后给
注意到这是一个卷积的形式,考虑使用生成函数刻画。设
直接做显然是优化不了的。注意到
取出树上的一条重链,考虑优化这上面的转移。设
由于轻儿子的
最终时间复杂度为
#include<bits/stdc++.h>
using namespace std;
using ui=unsigned int;
using ll=long long;
using ull=unsigned long long;
using i128=__int128;
using u128=__uint128_t;
using pii=pair<int,int>;
#define fi first
#define se second
constexpr int N=524290,mod=998244353,g=3;
inline ll add(ll x,ll y){return (x+=y)>=mod&&(x-=mod),x;}
inline ll Add(ll &x,ll y){return x=add(x,y);}
inline ll sub(ll x,ll y){return (x-=y)<0&&(x+=mod),x;}
inline ll Sub(ll &x,ll y){return x=sub(x,y);}
inline ll qpow(ll a,ll b){
ll res=1;
for(;b;b>>=1,a=a*a%mod)
if(b&1)res=res*a%mod;
return res;
}
int n;vector<int> Gr[N];
using poly=vector<ll>;
int lim,rev[N];ll ilim,w[N];
void initNTT(int n){
lim=1;
while(lim<=n)lim<<=1;
ilim=qpow(lim,mod-2);
for(int i=0;i<lim;i++)
rev[i]=(rev[i>>1]>>1)|((i&1)*(lim>>1));
for(int i=1;i<lim;i<<=1){
ll wn=qpow(g,(mod-1)/(i<<1)),cur=1;
for(int j=0;j<i;j++,cur=cur*wn%mod)w[i|j]=cur;
}
}
void NTT(ll *F,int type){
for(int i=0;i<lim;i++)
if(i<rev[i])
swap(F[i],F[rev[i]]);
for(int i=1;i<lim;i<<=1)
for(int j=0;j<lim;j+=i<<1)
for(int k=0;k<i;k++){
ll x=F[j|k],y=w[i|k]*F[i|j|k]%mod;
F[j|k]=add(x,y),F[i|j|k]=sub(x,y);
}
if(type==1)return;
reverse(F+1,F+lim);
for(int i=0;i<lim;i++)F[i]=F[i]*ilim%mod;
}
poly operator +(const poly &A,const poly &B){
static poly C;C.resize(max(A.size(),B.size()));
for(int i=0;i<(int)C.size();i++)C[i]=0;
for(int i=0;i<(int)A.size();i++)Add(C[i],A[i]);
for(int i=0;i<(int)B.size();i++)Add(C[i],B[i]);
return C;
}
poly operator *(const poly &A,const poly &B){
if(A.empty()||B.empty())return poly{};
int n=A.size()-1,m=B.size()-1;
static poly C;C.resize(n+m+1);
for(int i=0;i<=n+m;i++)C[i]=0;
if(1ll*n*m<=500){
for(int i=0;i<=n;i++)
for(int j=0;j<=m;j++)
C[i+j]=(C[i+j]+A[i]*B[j])%mod;
}
else{
static ll F[N],G[N];
for(int i=0;i<=n;i++)F[i]=A[i];
for(int i=0;i<=m;i++)G[i]=B[i];
initNTT(n+m);
for(int i=n+1;i<lim;i++)F[i]=0;
for(int i=m+1;i<lim;i++)G[i]=0;
NTT(F,1),NTT(G,1);
for(int i=0;i<lim;i++)F[i]=F[i]*G[i]%mod;
NTT(F,-1);
for(int i=0;i<=n+m;i++)C[i]=F[i];
}
return C;
}
int fat[N],siz[N],son[N];
void dfs1(int x,int fa){
siz[x]=1,fat[x]=fa;
for(auto &y:Gr[x])
if(y!=fa){
dfs1(y,x);
siz[x]+=siz[y];
if(siz[son[x]]<siz[y])
son[x]=y;
}
}
poly F[N],G[N];
poly solve1(const vector<int> &vec,int l,int r){
if(l+1==r)return F[vec[l]];
int mid=(l+r)>>1;
return solve1(vec,l,mid)*solve1(vec,mid,r);
}
pair<poly,poly> solve2(const vector<int> &vec,int l,int r){
if(l+1==r)return make_pair(poly{1},G[vec[l]]);
int mid=(l+r)>>1;
auto res1=solve2(vec,l,mid),res2=solve2(vec,mid,r);
return make_pair(res1.fi+res1.se*res2.fi,res1.se*res2.se);
}
void dfs2(int x,int fa){
vector<int> vec;
for(auto &y:Gr[x])
if(y!=fa){
dfs2(y,x);
if(y!=son[x])
vec.emplace_back(y);
}
if(!vec.size())G[x]=poly{1};
else G[x]=solve1(vec,0,vec.size());
if(son[fat[x]]!=x){
vec.clear(),vec.shrink_to_fit();
for(int u=x;u;u=son[u])vec.emplace_back(u);
auto res=solve2(vec,0,vec.size());
F[x]=res.se+poly{0,1}*res.fi;
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>n;
for(int i=2;i<=n;i++){
int p;cin>>p;
Gr[p].emplace_back(i);
}
dfs1(1,0),dfs2(1,0);
for(int i=1;i<(int)F[1].size();i++)cout<<F[1][i]<<'\n';
for(int i=(int)F[1].size();i<=n;i++)cout<<0<<'\n';
return 0;
}