标签:Directed sz head atARC121E int sum Tree 子树中 edge
令$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
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。