CF1097G Vladislav and a Great Legend
Description
A great legend used to be here, but some troll hacked Codeforces and erased it. Too bad for us, but in the troll society he earned a title of an ultimate-greatest-over troll. At least for them, it's something good. And maybe a formal statement will be even better for us?
You are given a tree $T$ with $n$ vertices numbered from $1$ to $n$ . For every non-empty subset $X$ of vertices of $T$ , let $f(X)$ be the minimum number of edges in the smallest connected subtree of $T$ which contains every vertex from $X$ .
You're also given an integer $k$ . You need to compute the sum of $(f(X))^k$ among all non-empty subsets of vertices, that is:
$$\sum\limits_{X \subseteq \{1, 2,\: \dots \:, n\},\, X \neq \varnothing} (f(X))^k.$$
Solution
首先:$n^m =\sum _{i=0}^m \begin{Bmatrix}m \\i\end{Bmatrix}n^{\underline{i} }$
发现需要求的是$\binom{f(S)}{i}$,$S$取遍全集的所有非空子集
设$f_{i,j}$表示其子树的所有子集与$i$的父节点组成的虚树边数中选出$j$条边的方案数
可以树形背包合并子树,复杂度$O(nk)$
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<vector> #include<cstdio> #include<cmath> using namespace std; int n,K,siz[100005]; const int mod=1e9+7; long long S[205][205],fac[205],ans[205],dp[100005][205],ret; vector<int>e[100005]; inline int read(){ int f=1,w=0; char ch=0; while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9')w=(w<<1)+(w<<3)+ch-'0',ch=getchar(); return f*w; } void dfs(int k,int f){ siz[k]=dp[k][0]=1; for(int i=0;i<e[k].size();i++){ int v=e[k][i]; if(v!=f){ dfs(v,k); for(int j=min(K,siz[k]);~j;j--)for(int l=min(K-j,siz[v]);~l;l--){ long long temp=dp[k][j]*dp[v][l]%mod; (ans[j+l]+=temp)%=mod,(dp[k][j+l]+=temp)%=mod; } for(int j=0;j<=min(K,siz[v]);j++)(dp[k][j]+=dp[v][j])%=mod; siz[k]+=siz[v]; } } for(int i=min(K,siz[k]);~i;i--)(dp[k][i+1]+=dp[k][i])%=mod; } int main(){ n=read(),K=read(),S[1][1]=1,fac[1]=1; for(int i=1;i<n;i++){ int x=read(),y=read(); e[x].push_back(y),e[y].push_back(x); } for(int i=2;i<=K;i++)for(int j=1;j<=i;j++)S[i][j]=(S[i-1][j-1]+j*S[i-1][j]%mod)%mod; for(int i=2;i<=K;i++)fac[i]=fac[i-1]*i%mod; dfs(1,0); for(int i=0;i<=K;i++)(ret+=S[K][i]*fac[i]%mod*ans[i]%mod)%=mod; printf("%lld\n",ret); return 0; }