zoukankan      html  css  js  c++  java
  • [国家集训队]Crash的文明世界

    Description

    Luogu4827
    BZOJ2159

    给定一棵树,对于每个点(x),求出(sumlimits_{i=1}^n dist(x, i)^k)

    Solution

    (x^k)有关的题目,基本都要扯到第二类斯特林数上

    啥是第二类斯特林数?第二类斯特林数(ig{^x_kig})表示将(x)个元素分成(k)个非空子集的方案数,(ig{^x_kig}=ig{^{x-1}_{k-1}ig}+kig{^{x-1}_kig})
    这东西和(x^k)咋扯上的关系咧?(x^k = sum_{i=1}^k ig{^k_iig} cdot A_x^i),思考这个式子的组合意义就好了。当然这个式子也可以变形成(sum_{i=1}^k ig{^k_iig} cdot i! {xchoose i})

    然后变形一下原来的式子(sumlimits_{i=1}^n dist(x, i)^k = sumlimits_{i=1}^n sum_{j=1}^k ig{^k_jig} cdot j! {dist(x, i)choose i}),然后就是交换一下求和顺序,预处理前两项,树形DP最后一项即可。

    Code

    #include <cstdio>
    #include <vector>
    
    const int N = 5e4 + 10;
    const int M = 2 * N;
    const int MOD = 10007;
    
    int n, K;
    std::vector<int> g[N];
    int fa[N];
    int S[155][155]; // 斯特林数 
    int fct[155]; // 阶乘
    int u[N][155], d[N][155], ans[N]; 
    
    void dfs1(int x, int fa) {
    	d[x][0] = 1;
    	for (int i : g[x]) if (i != fa) {
    		dfs1(i, x);
    		d[x][0] = (d[x][0] + d[i][0]) % MOD;
    		for (int j = 1; j <= K; ++j) {
    			d[x][j] = (d[x][j] + d[i][j-1] + d[i][j]) % MOD;
    		}
    	}
    }
    
    void dfs2(int x, int fa) {
    	u[x][0] = n-d[x][0];
    	if (fa) for (int i = 1; i <= K; ++i) {
    		u[x][i] = 
    			u[fa][i] + d[fa][i] - d[x][i] - d[x][i-1] + 
    			u[fa][i-1] + d[fa][i-1] - d[x][i-1] - d[x][i-2]
    			+ 4 * MOD;
    		u[x][i] %= MOD;
    	}
    	for (int i : g[x]) if (i != fa) dfs2(i, x);
    }
    
    int main() {
    	scanf("%d%d", &n, &K);
    	for (int i = 1, x, y; i < n; ++i) {
    		scanf("%d%d", &x, &y);
    		g[x].push_back(y);
    		g[y].push_back(x);
    	}
    	S[1][1] = 1;
    	for (int i = 2; i <= K; ++i) {
    		for (int j = 1; j <= K; ++j) {
    			S[i][j] = (S[i-1][j-1] + S[i-1][j]*j) % MOD;
    		}
    	}
    	fct[1] = 1;
    	for (int i = 2; i <= K; ++i) fct[i] = i * fct[i-1] % MOD;
    	dfs1(1, 0);
    	dfs2(1, 0);
    	for (int i = 1; i <= n; ++i) {
    		for (int j = 1; j <= K; ++j) {
    			ans[i] = (ans[i] + S[K][j]*fct[j]%MOD * (u[i][j]+d[i][j])%MOD) % MOD;
    		}
    		printf("%d
    ", ans[i]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    c++11强制转化类型
    关于parent指针以及对话框属性
    关于connect函数(Qt)
    lambda表达式
    学习过程中要注意的一些问题
    自动类型转换
    gakki
    排序算法(2)——简单选择排序和直接插入排序
    [Leetcode]414. Third Maximum Number
    [Leetcode]283. Move Zeroes
  • 原文地址:https://www.cnblogs.com/wyxwyx/p/lg4827.html
Copyright © 2011-2022 走看看