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)$

#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;
}
Vladislav and a Great Legend

 

posted @ 2021-03-15 11:26  QDK_Storm  阅读(94)  评论(0编辑  收藏  举报