题解:P14016 [ICPC 2024 Nanjing R] 拓扑
设
然后考虑
现在我们来考虑证明一下,首先根据题意
然后手动把组合数展开并且约分,可以得到:
然后再乘上各个子结点子树的方案数(由于子结点的子树并没有祖先后代关系,因此互不影响),得到:
通过展开后面的
类似地,可以算出对于
整理一下:
算出
然后这个转移显然是
统计答案时,由于只有
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5005;
const int mod=998244353;
int n,fa[N],sz[N],H[N],invH[N];
int fac[N],ifac[N];
unsigned dp[N][N];
vector<int> ed[N];
int qpow(int a,int b)
{
int res=1;
while(b)
{
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
int C(int n,int m)
{
if(n<0 or m<0 or n<m) return 0;
return fac[n]*ifac[m]%mod*ifac[n-m]%mod;
}
signed main()
{
cin>>n;
for(int i=2;i<=n;i++)
{
cin>>fa[i];
ed[fa[i]].push_back(i);
}
for(int i=1;i<=n;i++)
sz[i]=1,H[i]=1;
for(int i=n;i>=2;i--)
sz[fa[i]]+=sz[i];
for(int i=1;i<=n;i++)
H[i]=sz[i];
for(int i=n;i>=2;i--)
H[fa[i]]=H[fa[i]]*H[i]%mod;
for(int i=1;i<=n;i++)
invH[i]=qpow(H[i],mod-2);
fac[0]=1;
for(int i=1;i<=n;i++)
fac[i]=fac[i-1]*i%mod;
ifac[n]=qpow(fac[n],mod-2);
for(int i=n;i>=1;i--)
ifac[i-1]=ifac[i]*i%mod;
dp[1][1]=1;
for(int i=1;i<=n;i++)
for(auto u:ed[i])
{
int m=sz[i]-sz[u]-1;
int P=fac[m]*sz[i]%mod*H[u]%mod*invH[i]%mod;
for(int k=1;k<=n-sz[u]+1;k++)
{
dp[u][k]=dp[u][k-1];
if(k>=2)
{
int val=dp[i][k-1]*C(n-k+1-sz[u],m)%mod;
val=val*P%mod;
dp[u][k]=(dp[u][k]+val)%mod;
}
}
}
for(int i=1;i<=n;i++)
{
int g=fac[sz[i]]*invH[i]%mod;
int ans=dp[i][i]*g%mod*C(n-i,sz[i]-1)%mod;
cout<<ans;
if(i<n) cout<<' ';
}
cout<<'\n';
return 0;
}