zoukankan      html  css  js  c++  java
  • bzoj 2159

    Description

    给定一棵(nle 10^5)的树, 和(kle 150)

    求每个点(x)的$$S(x) = sum_{y=1}^n dis(x, y) ^ k$$

    Analysis

    k比较小, 考虑斯特林展开

    [egin{aligned} S(x) &= sum_{y=1}^n dis(x, y)^k\ &=sum_{y=1}^n sum_{i=0}^k left{egin{matrix}k\iend{matrix} ight} i!inom{dis(x,y)}{i}\ &=sum_{i=0}^k left{egin{matrix}k\iend{matrix} ight} i! sum_{y=1}^n inom{dis(x,y)}{i}\ end{aligned} ]

    考虑求后面的部分, 可以上下树形dp一下

    记$$f[x][i] = sum_{yin sub(x)} inom{dis(x, y)}{i}$$

    那么$$f[x][i] = sum_{yin son(x)} f[y][i] + [i>0]f[y][i-1]$$

    即利用$$Delta inom x c = inom x {c-1}$$

    这题只用暴力转移组合数一次

    Code

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <cctype>
    #define rep(i,a,b) for (int i = (a); i <= (b); ++ i)
    #define per(i,a,b) for (int i = (a); i >= (b); -- i)
    #define For(i,a,b) for (int i = (a); i < (b); ++ i)
    using namespace std;
    const int N = 5e4 + 7;
    const int M = 157;
    const int Q = 10007;
    
    inline int ri(){
    	int x = 0; bool f = 1; char c = getchar();
    	for (; !isdigit(c); c = getchar()) if (c == '-') f = 0;
    	for (; isdigit(c); c = getchar()) x = x*10+c-48;
    	return f ? x : -x;
    }
    
    inline int pls(int x, int y) {return (x + y) % Q;}
    inline int mns(int x, int y) {return pls(x, Q - y);}
    inline int mul(int x, int y) {return x * y % Q;}
    
    int n, m;
    int fac[M], S2[M][M];
    int f[N][M], g[N][M];
    int ans[N];
    
    struct vec {
    	int g[N], te;
    	struct edge{int y, nxt;}e[N << 1];
    	inline void push(int x, int y) {e[++te] = (edge){y, g[x]}; g[x] = te;}
    	inline void push2(int x, int y) {push(x, y); push(y, x);}
    	inline int& operator () (int x) {return g[x];}
    	inline edge& operator [] (int x) {return e[x];}
    }e;
    
    void upd(int *A, int *B, int kd = 1) {
    	if (kd == 1) {
    		rep (i, 0, m) A[i] = pls(A[i], B[i]);
    		rep (i, 1, m) A[i] = pls(A[i], B[i-1]);
    	}
    	if (kd == -1) {
    		rep (i, 0, m) A[i] = mns(A[i], B[i]);
    		rep (i, 1, m) A[i] = mns(A[i], B[i-1]);
    	}
    }
    
    void UP(int x, int fa) {
    	int p, y;
    
    	rep (i, 0, m) ans[x] = pls(ans[x], mul(S2[m][i], pls(g[x][i], f[x][i])));
    	
    	for (p=e(x); p; p=e[p].nxt)
    	if ((y=e[p].y) != fa) {
    		upd(f[x], f[y], -1);
    
    		upd(g[y], f[x]);
    		upd(g[y], g[x]);
    		UP(y, x);
    
    		upd(f[x], f[y]);
    	}
    }
    
    void DW(int x, int fa) {
    	int p, y;
    	for (p=e(x); p; p=e[p].nxt)
    	if ((y=e[p].y) != fa) {
    		DW(y, x);
    		upd(f[x], f[y]);
    	}
    	f[x][0] = pls(f[x][0], 1); // d(x, x) = 0   
    }
    
    void Uncompress() {
    	int L, i, now, A, B, mod, tmp;
    	scanf("%d%d%d", &n, &m, &L);
    	scanf("%d%d%d%d", &now, &A, &B, &mod);
    	for (i = 1; i < n; i ++) {
    		now = (now * A + B) % mod;
    		tmp = (i < L) ? i : L;
    		e.push2(i - now % tmp, i + 1);
    	}
    } 
    
    int main() {
    #ifndef ONLINE_JUDGE
    	freopen("a.in", "r", stdin);
    #endif
    
    	Uncompress();
    
    	int i, j;
    	for (fac[0] = 1, i=1; i<=m; ++i) fac[i] = mul(fac[i-1], i);
    
    	for (S2[0][0] = 1, i=1; i<=m; ++i)
    	for (j=1; j<=i; ++j) S2[i][j] = pls(mul(j, S2[i-1][j]), S2[i-1][j-1]);
    	rep (i, 0, m) rep (j, 0, i) S2[i][j] = mul(S2[i][j], fac[j]);
    
    	DW(1, 0);
    	UP(1, 0);
    
    	rep (i, 1, n) printf("%d
    ", ans[i]);
    
    	return 0;
    }
    
  • 相关阅读:
    《区块链100问》第38集:比特币钱包是干嘛的?
    《区块链100问》第39集:冷钱包热钱包
    《区块链100问》第40集:全节点钱包和轻钱包
    《区块链100问》第41集:比特币可以用于支付吗?
    《区块链100问》第42集:区块链和比特币的关系
    《区块链100问》第43集:区块链技术发展史
    KindEditor使用
    Django之验证码
    Django之ModelForm
    Django之Form详解
  • 原文地址:https://www.cnblogs.com/acha/p/7577368.html
Copyright © 2011-2022 走看看