P4827 [国家集训队] Crash 的文明世界
传送门:洛谷
题目大意:设$$S(i)=\sum_{j=1}^ndis(i,j)^k$$,求$S(1),S(2),\ldots,S(n)$。
数据范围:$n\leq 50000,k\leq 150$
这道题,看见$k$次方和就直接上斯特林数。
$$S(x)=\sum_{i=0}^ki!S(k,i)\sum_{y=1}^nC_{dis(x,y)}^i$$
然后我们考虑求最后一项。
设$$up_{x,t}=\sum_{y\notin x}C_{dis(x,y)}^t,dn_{x,t}=\sum_{y\in x}C_{dis(x,y)}^t$$
我们先考虑$dn$。
$$dn_{x,t}=\sum_{(x,v)}\sum_{y\in v}C_{dis(v,y)+1}^t$$
$$=\sum_{(x,v)}\sum_{y\in v}(C_{dis(v,y)}^t+C_{dis(v,y)}^{t-1})$$
$$=\sum_{(x,v)}(dn_{v,t}+dn_{v,t-1})$$
然后考虑$up$
$$up_{x,t}=\sum_{v\notin fa}C_{dis(v,fa)+1}^t+\sum_{v\in fa}C_{dis(v,fa)+1}^t-\sum_{v\in x}C_{dis(v,x)+2}^t$$
$$=up_{fa,t}+up_{fa,t-1}+dn_{fa,t}+dn_{fa,t-1}-dn_{x,t}-2dn_{x,t-1}-dn_{x,t-2}$$
其中$up_{1,t}=0$
然后把式子直接输进去就可以了。
1 #include<cstdio> 2 #define Rint register int 3 using namespace std; 4 const int N = 50003, K = 153, mod = 10007; 5 int n, k, head[N], to[N << 1], nxt[N << 1], S[K][K], fac[K]; 6 inline void add(int a, int b){ 7 static int cnt = 0; 8 to[++ cnt] = b; nxt[cnt] = head[a]; head[a] = cnt; 9 } 10 int dn[N][K], up[N][K]; 11 inline void dfs1(int x, int f){ 12 dn[x][0] = 1; 13 for(Rint i = head[x];i;i = nxt[i]) 14 if(to[i] != f){ 15 dfs1(to[i], x); 16 dn[x][0] = (dn[x][0] + dn[to[i]][0]) % mod; 17 for(Rint t = 1;t <= k;t ++) 18 dn[x][t] = (dn[to[i]][t] + dn[to[i]][t - 1] + dn[x][t]) % mod; 19 } 20 } 21 inline void dfs2(int x, int f){ 22 for(Rint i = head[x];i;i = nxt[i]) 23 if(to[i] != f){ 24 up[to[i]][0] = (up[x][0] + dn[x][0] - dn[to[i]][0] + mod) % mod; 25 up[to[i]][1] = (up[x][0] + up[x][1] + dn[x][0] + dn[x][1] - dn[to[i]][1] - 2 * dn[to[i]][0] + 3 * mod) % mod; 26 for(Rint t = 2;t <= k;t ++) 27 up[to[i]][t] = (up[x][t] + up[x][t - 1] + dn[x][t] + dn[x][t - 1] - dn[to[i]][t] - 2 * dn[to[i]][t - 1] - dn[to[i]][t - 2] + 4 * mod) % mod; 28 dfs2(to[i], x); 29 } 30 } 31 int main(){ 32 scanf("%d%d", &n, &k); 33 S[0][0] = 1; 34 for(Rint i = 1;i <= k;i ++) 35 for(Rint j = 1;j <= k;j ++) 36 S[i][j] = (S[i - 1][j - 1] + S[i - 1][j] * j) % mod; 37 fac[0] = 1; 38 for(Rint i = 1;i <= k;i ++) fac[i] = i * fac[i - 1] % mod; 39 for(Rint i = 1;i < n;i ++){ 40 int a, b; 41 scanf("%d%d", &a, &b); 42 add(a, b); add(b, a); 43 } 44 dfs1(1, 0); dfs2(1, 0); 45 for(Rint x = 1;x <= n;x ++){ 46 int ans = 0; 47 for(Rint i = 0;i <= k;i ++) 48 ans = (ans + fac[i] * S[k][i] % mod * (up[x][i] + dn[x][i]) % mod) % mod; 49 printf("%d\n", ans); 50 } 51 }