[cf1097G]Vladislav and a Great Legend

记$S(n,m)$为第二类斯特林数,表示将$n$个不同的球放入$m$个相同的盒子中,不允许有空的方案数,则有转移式$S(n,m)=S(n-1,m-1)+m\cdot S(n-1,m)$(考虑最后一个球)

对于$m^{k}$,即将$k$个不同的球放入$m$个不同的盒子中,允许有空的方案数,枚举空盒的数目与盒子的选择,那么即有$m^{k}=\sum_{i=0}^{k}i!\cdot c(m,i)\cdot S(k,i)$

代入题中,即$\sum_{X}f(X)^{k}=\sum_{i=0}^{k}i!\cdot S(k,i)\cdot \sum_{X}c(f(X),i)$,后者即从虚树中选择$i$条边,考虑dp

设$f[k][i]=\sum_{X的虚树根在k子树中}c(f(X),i)$,转移枚举儿子$son$并分类讨论:

1.$lca$在$son$这棵子树中,$(k,son)$不能选,即$f[k][i]+=f[son][i]$

2.否则,类似背包的转移,枚举原来选的边,$(k,son)$任意,即$f[k][i+j+0/1]+=f[k][i]\cdot f[son][j]$

但这样还有一个问题,在第2种转移中,如果初始lca不为$k$,但加入另一棵子树后lca必然为$k$,那么无法考虑原来的子树到根的路径

考虑强制$(k,son)$都可以选,那么第1类转移变为$f[k][i]+=f[son][i]+f[son][i-1]$,但这样答案应该是每一次乘积的和,即保证了这些$(k,son)$的边都可以选

这样的复杂度看上去是$o(nk^{2})$的,但注意到$i$的范围是$\min(sz,k)$,简单分析可以发现是$o(nk)$的

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 100005
 4 #define mod 1000000007
 5 struct ji{
 6     int nex,to;
 7 }edge[N<<1];
 8 int E,n,m,x,y,ans,head[N],sz[N],g[205],s[205][205],sum[205],f[N][205];
 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,int fa){
15     sz[k]=f[k][0]=1;
16     for(int i=head[k];i!=-1;i=edge[i].nex)
17         if (edge[i].to!=fa){
18             int v=edge[i].to;
19             dfs(v,k);
20             memcpy(g,f[k],sizeof(g));
21             for(int j=0;j<=sz[v];j++)f[k][j]=(f[k][j]+f[v][j])%mod;
22             for(int j=1;j<=sz[v];j++)f[k][j]=(f[k][j]+f[v][j-1])%mod;
23             for(int j=0;j<=sz[k];j++)
24                 for(int l=0;(l<=sz[v])&&(j+l<=m);l++){
25                     f[k][j+l]=(f[k][j+l]+1LL*g[j]*f[v][l])%mod;
26                     sum[j+l]=(sum[j+l]+1LL*g[j]*f[v][l])%mod;
27                     f[k][j+l+1]=(f[k][j+l+1]+1LL*g[j]*f[v][l])%mod;
28                     sum[j+l+1]=(sum[j+l+1]+1LL*g[j]*f[v][l])%mod;
29                 }
30             sz[k]=min(sz[k]+sz[v],m);
31         }
32 }
33 int main(){
34     scanf("%d%d",&n,&m);
35     memset(head,-1,sizeof(head));
36     for(int i=1;i<n;i++){
37         scanf("%d%d",&x,&y);
38         add(x,y);
39         add(y,x);
40     }
41     s[0][0]=1;
42     for(int i=1;i<=m;i++)
43         for(int j=1;j<=m;j++)s[i][j]=(s[i-1][j-1]+1LL*j*s[i-1][j])%mod;
44     dfs(1,0);
45     int fac=1;
46     for(int i=1;i<=m;i++){
47         fac=1LL*fac*i%mod;
48         ans=(ans+1LL*fac*s[m][i]%mod*sum[i])%mod;
49     }
50     printf("%d",ans); 
51 }
View Code

 

posted @ 2020-10-20 11:01  PYWBKTDA  阅读(147)  评论(0编辑  收藏  举报