当前位置 : 主页 > 大数据 > 区块链 >

CF1097G Vladislav and a Great Legend

来源:互联网 收集:自由互联 发布时间:2021-06-22
传送门 题目大意 一棵$n$个点的树,一个点集$S$的权值定义为把这个点击连成一个联通块的最少边数,求: $$ans=\sum_{S\in U}f(S)^k$$ 题解 这题跟gdoi那道题差不多 先把柿子化一下变成 $$an

传送门


 

题目大意

一棵$n$个点的树,一个点集$S$的权值定义为把这个点击连成一个联通块的最少边数,求:

$$ans=\sum_{S\in U}f(S)^k$$


题解

这题跟gdoi那道题差不多

先把柿子化一下变成

$$ans=\sum_{i=0}^k \begin{Bmatrix}k\\i\end{Bmatrix} i! \sum_{S\in U}\begin{pmatrix}f(S)\\i\end{pmatrix}$$

然后我们就相当于去统计大小为$i$的边集的贡献

这个可以通过dp来实现

定义$f_{x,i}$表示$x$子树内所有点与父亲的连边中选出了$i$条边,子树内选择的点的方案数

dp过程就是首先算出不包括$x$和父亲的边的方案数,然后再加上这条边就可以了

在$x$和父亲的边加入边集时,要注意$x$的子树内外会不会一个点都没选

减去这些方案就可以了


 

Code

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#define LL long long
using namespace std;
const LL Maxn = 100010;
const LL Maxk = 210;
const LL Mod = 1e9+7;
LL f[Maxn][Maxk], g[Maxk];
LL h[Maxk];
LL n, K;
struct node {
	LL y, next;
}a[Maxn<<1]; LL first[Maxn], len;
void ins(LL x, LL y) {
	len++;
	a[len].y = y;
	a[len].next = first[x]; first[x] = len;
}
LL Str2[Maxk][Maxk], jc[Maxk];
LL siz[Maxn];
void up(LL &x, LL y) { x = (x + y) % Mod; }
void dfs(LL x, LL fa) {
	f[x][0] = 2;
	siz[x] = 1;
	for(LL k = first[x]; k; k = a[k].next){
		LL y = a[k].y;
		if(y == fa) continue;
		dfs(y, x);
		for(LL i = 0; i < siz[x]+siz[y] && i <= K; i++) g[i] = 0;
		for(LL i = 0; i < siz[x] && i <= K; i++){
			for(LL j = 0; j <= siz[y] && j <= K-i; j++) up(g[i+j], f[x][i]*f[y][j]);
		}
		siz[x] += siz[y];
		for(LL i = 0; i < siz[x] && i <= K; i++) f[x][i] = g[i];
	}
	if(x != 1){
		for(LL i = 0; i < K; i++){
			up(h[i+1], Mod-f[x][i]);
			if(i == 0) up(h[1], 1);
		}
	} else for(LL i = 1; i <= K; i++) up(h[i], f[x][i]);
	for(LL i = K; i > 0; i--) up(f[x][i], f[x][i-1]);
	up(f[x][1], Mod-1);
}
int main() {
	LL i, j, k;
	scanf("%lld%lld", &n, &K);
	Str2[0][0] = 1;
	for(i = 1; i <= K; i++){
		for(j = 1; j <= i; j++) Str2[i][j] = (j*Str2[i-1][j]+Str2[i-1][j-1])%Mod;
	}
	jc[0] = 1;
	for(i = 1; i <= K; i++) jc[i] = jc[i-1]*i%Mod;
	for(i = 1; i < n; i++){
		LL x, y;
		scanf("%lld%lld", &x, &y);
		ins(x, y); ins(y, x);
	}
	dfs(1, 0);
	LL ans = 0;
	for(i = 1; i <= K; i++) up(ans, Str2[K][i]*jc[i]%Mod*h[i]);
	printf("%lld\n", ans);
	return 0;
}
网友评论