[atARC121E]Directed Tree
作者:互联网
令$b_{a_{i}}=i$,那么问题即要求$i$不是$b_{i}$的祖先,也即$b_{i}$不严格在$i$的子树中
显然$a_{i}$和$b_{i}$一一对应,因此我们不妨统计$b_{i}$的个数
考虑容斥,令$f(S)$为$\forall i\in S,b_{i}$严格在$i$子树中的排列数,根据容斥答案即$\sum_{S\subseteq [1,n]}(-1)^{|S|}f(S)$
关于$f(S)$,可以从底往上依次确定$i\in S$的$b_{i}$,方案数即$\prod_{i\in S}sz_{i}-\sum_{x\in S且x在i的子树中}1$(其中$sz_{i}$为$i$的子树大小),最后对于$i\not\in S$的$b_{i}$没有限制,即$(n-|S|)!$种
对于后者,可以在树形dp中记录,即令$f_{i,j}$表示以$i$为根的子树中$\sum_{x\in S且x在i的子树中}1=j$的排列数,最终不难得到答案即$\sum_{i=1}^{n}(-1)^{i}(n-i)!f_{1,i}$
转移方程即$f_{i,j+k}=\sum f_{i,j}f_{son,k}$,最终再将$i$加入$S$,即$f_{i,j}=f_{i,j}+(sz_{i}-j)f_{i,j-1}$
时间复杂度为$o(n^{2})$,可以通过
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 2005 4 #define mod 998244353 5 struct Edge{ 6 int nex,to; 7 }edge[N]; 8 int E,n,x,ans,head[N],sz[N],g[N],f[N][N]; 9 void add(int x,int y){ 10 edge[E].nex=head[x]; 11 edge[E].to=y; 12 head[x]=E++; 13 } 14 void dfs(int k){ 15 f[k][0]=1; 16 for(int i=head[k];i!=-1;i=edge[i].nex){ 17 dfs(edge[i].to); 18 memcpy(g,f[k],sizeof(g)); 19 memset(f[k],0,sizeof(f[k])); 20 for(int j=0;j<=sz[k];j++) 21 for(int l=0;l<=sz[edge[i].to];l++)f[k][j+l]=(f[k][j+l]+1LL*g[j]*f[edge[i].to][l])%mod; 22 sz[k]+=sz[edge[i].to]; 23 } 24 sz[k]++; 25 for(int i=sz[k];i;i--)f[k][i]=(f[k][i]+1LL*(sz[k]-i)*f[k][i-1])%mod; 26 } 27 int main(){ 28 scanf("%d",&n); 29 memset(head,-1,sizeof(head)); 30 for(int i=2;i<=n;i++){ 31 scanf("%d",&x); 32 add(x,i); 33 } 34 dfs(1); 35 for(int i=0;i<=n;i++){ 36 int s=1; 37 if (i&1)s=mod-1; 38 for(int j=1;j<=n-i;j++)s=1LL*s*j%mod; 39 ans=(ans+1LL*s*f[1][i])%mod; 40 } 41 printf("%d",ans); 42 }View Code
标签:Directed,sz,head,atARC121E,int,sum,Tree,子树中,edge 来源: https://www.cnblogs.com/PYWBKTDA/p/14973642.html