• BZOJ2159 Crash的文明世界


    Description

    传送门
    给你一个n个点的树,边权为1. 对于每个点u, 求:(sum_{i = 1}^{n} distance(u, i)^{k})
    $ n leq 50000, k leq 150 $

    Solution

    咱们化一下式子:
    (sum_{i = 1}^{n} distance(u,i) ^ {k})
    (=sum_{i = 1}^{n} sum_{j = 0}^{k} C(dis(u, i), j)* S2(k, j) * j!)
    (=sum_{j = 0}^{k} S2(k,j) * j! * sum_{i = 1}^{n} C(dis(u, i), j))
    (dp[u][j] = sum_{i = 1}^{n} C(dis(u, i), j))

    那么设$down[u][j] $ 表示(i in subtree[u])的解, (up[u][j])表示$ i in tree - subtree[u]$的解

    那么显然, 根据组合数性质:$${n choose k} = {n - 1 choose k} + {n - 1 choose k - 1}$$

    [down[u][j] = down[son][j - 1] + down[son][j] ]

    [up[x][k]=up[x][k]+up[fa][k]+up[fa][k-1] ]

    [up[x][k]=up[x][k]+down[fa][k]+down[fa][k-1] ]

    [up[x][k]=up[x][k]-down[x][k]-down[x][k-1] ]

    [up[x][k]=up[x][k]-down[x][k-1]-down[x][k-2] ]

    Codes

    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i, a, b) for(int i = (a), i##_end_ = (b); i <= i##_end_; ++i)
    #define drep(i, a, b) for(int i = (a), i##_end_ = (b); i >= i##_end_; --i)
    #define clar(a, b) memset((a), (b), sizeof(a))
    #define debug(...) fprintf(stderr, __VA_ARGS__)
    #define Debug(s) debug("The massage in line %d, Function %s: %s
    ", __LINE__, __FUNCTION__, s)
    typedef long long LL;
    typedef long double LD;
    const int BUF_SIZE = (int)1e6 + 10;
    struct fastIO {
        char buf[BUF_SIZE], buf1[BUF_SIZE];
        int cur, cur1;
        FILE *in, *out;
        fastIO() {
            cur = BUF_SIZE, in = stdin, out = stdout;
    		cur1 = 0;
        }
        inline char getchar() {
            if(cur == BUF_SIZE) fread(buf, BUF_SIZE, 1, in), cur = 0;
            return *(buf + (cur++));
        }
        inline void putchar(char ch) {
            *(buf1 + (cur1++)) = ch;
            if (cur1 == BUF_SIZE) fwrite(buf1, BUF_SIZE, 1, out), cur1 = 0;
        }
        inline int flush() {
            if (cur1 > 0) fwrite(buf1, cur1, 1, out);
            return cur1 = 0;
        }
    }IO;
    #define getchar IO.getchar
    #define putchar IO.putchar
    int read() {
    	char ch = getchar();
    	int x = 0, flag = 1;
    	for(;!isdigit(ch); ch = getchar()) if(ch == '-') flag *= -1;
    	for(;isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
    	return x * flag;
    }
    void write(int x) {
    	if(x < 0) putchar('-'), x = -x;
    	if(x >= 10) write(x / 10);
    	putchar(x % 10 + 48);
    }
    void putString(char s[], char EndChar = '
    ') {
    	rep(i, 0, strlen(s) - 1) putchar(*(s + i));
    	if(~EndChar) putchar(EndChar);
    }
    
    #define Mod 10007
    #define Maxn 50009
    #define Maxk 159
    struct edge {
    	int to, nxt;
    }g[Maxn << 1];
    int n, k, head[Maxn], e, fac[Maxn], up[Maxn][Maxk], down[Maxn][Maxk], s[Maxk][Maxk];
    namespace INIT {
    	void add(int u, int v) {
    		g[++e] = {v, head[u]}, head[u] = e;
    	}
    	void Main() {
    		clar(head, -1);
    		n = read(), k = read();
    		rep(i, 1, n - 1) {
    			int u = read(), v = read();
    			add(v, u), add(u, v);
    		}
    		s[0][0] = 1;
    		rep(i, 1, k)
    			rep(j, 1, i) s[i][j] = (s[i - 1][j - 1] + j * s[i - 1][j]) % Mod;
    		fac[0] = 1;
    		rep(i, 1, k) fac[i] = fac[i - 1] * i % Mod;
    	}
    }
    namespace SOLVE {
    	int S[Maxn];
    	void dfs(int u, int fa) {
    		down[u][0] = 1;
    		for(int i = head[u]; ~i; i = g[i].nxt) {
    			int v = g[i].to;
    			if(v != fa) {
    				dfs(v, u);
    				(down[u][0] += down[v][0]) %= Mod;
    				rep(j, 1, k) (down[u][j] += (down[v][j] + down[v][j - 1]) % Mod) %= Mod;
    			}
    		}
    	}
    	void dfs1(int u, int fa) {
    		for(int i = head[u]; ~i; i = g[i].nxt) {
    			int v = g[i].to;
    			if(v != fa) {
    				up[v][0] = (n - down[v][0]) % Mod;
    				rep(j, 1, k) {
    					(up[v][j] += up[u][j - 1] + up[u][j]) %= Mod;
    					(up[v][j] += down[u][j - 1] + down[u][j]) %= Mod;
    					(up[v][j] -= (down[v][j - 1] + down[v][j - 2]) % Mod - Mod) %= Mod;
    					(up[v][j] -= (down[v][j - 1] + down[v][j]) % Mod - Mod) %= Mod;
    				}
    				dfs1(v, u);
    			}
    		}
    	}
    	void Main() {
    		dfs(1, 0), dfs1(1, 0);
    		rep(i, 1, k) {
    			int Tmp = fac[i] * s[k][i] % Mod;
    			rep(j, 1, n) S[j] += (Tmp * (up[j][i] + down[j][i])) % Mod;
    		}
    		rep(i, 1, n) printf("%d
    ", S[i] % Mod);
    	}
    }
    int main() {
    #ifdef Qrsikno
    	freopen("BZOJ2159.in", "r", stdin);
    	freopen("BZOJ2159.out", "w", stdout);
    #endif
    	INIT :: Main();
    	SOLVE :: Main();
    #ifdef Qrsikno
    	debug("
    Running time: %.3lf(s)
    ", clock() * 1.0 / CLOCKS_PER_SEC);
    #endif
    	return IO.flush();
    }
    
  • 相关阅读:
    java
    java
    java
    js
    java
    异常之异常处理
    面向对象之元类
    面向对象之内置方法
    面向对象之反射
    面向对象之类方法与静态方法
  • 原文地址:https://www.cnblogs.com/qrsikno/p/9791296.html
Copyright © 2020-2023  润新知