[BZOJ2159]Crash的文明世界(斯特林数+树形DP)

题意:给定一棵树,求$S(i)=\sum_{j=1}^{n}dist(i,j)^k$。
题解:根据斯特林数反演得到:$n^m=\sum_{i=0}^{n}C(n,i)\times i!\times S(m,i)$
故$S(i)=\sum_{k=1}^{m}S(m,k)\times k!\times\sum_{j=1}^{n}C(dist(i,j),k)$
用$f[i][k]$表示$C(dist(i,j),k)$,通过$Pascal$公式:$C(n,m)=C(n,m-1)+C(n-1,m-1)$,用树形DP得到答案。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 4 #define For(i,x) for (int i=h[x],k; i; i=nxt[i])
 5 using namespace std;
 6 
 7 const int N=50010,K=160,mod=10007;
 8 int n,m,l,u,v,now,cnt,A,B,Q,tmp,p[N],f[N][K],S[K][K],fac[K],ans[N];
 9 int to[N<<1],nxt[N<<1],h[N];
10 void add(int u,int v){ to[++cnt]=v; nxt[cnt]=h[u]; h[u]=cnt; }
11 
12 void dfs(int x,int fa){
13     f[x][0]=1;
14     For(i,x) if ((k=to[i])!=fa){
15         dfs(k,x); f[x][0]=(f[x][0]+f[k][0])%mod;
16         rep(j,1,m) f[x][j]=(f[x][j]+f[k][j]+f[k][j-1])%mod;
17     }
18 }
19 
20 void getans(int x,int fa){
21     rep(i,0,m) ans[x]=(ans[x]+f[x][i]*fac[i]%mod*S[m][i])%mod;
22     For(i,x) if ((k=to[i])!=fa){
23         for (int j=m; j>=2; j--)
24             f[k][j]=((f[x][j]-f[k][j-1]+f[x][j-1]-f[k][j-1]-f[k][j-2])%mod+mod)%mod;
25         f[k][1]=((f[x][1]-f[k][0]+f[x][0]-f[k][0])%mod+mod)%mod; f[k][0]=n;
26         getans(k,x);
27     }
28 }
29 
30 int main(){
31     scanf("%d%d",&n,&m);
32     rep(i,1,n-1) scanf("%d%d",&u,&v),add(u,v),add(v,u);
33     dfs(1,1);
34     fac[0]=1; rep(i,1,m) fac[i]=fac[i-1]*i%mod;
35     S[0][0]=1;
36     rep(i,1,m) rep(j,1,i) S[i][j]=(S[i-1][j-1]+S[i-1][j]*j)%mod;
37     getans(1,1);
38     rep(i,1,n) printf("%d\n",ans[i]);
39     return 0;
40 }

 

posted @ 2018-08-29 18:03  HocRiser  阅读(187)  评论(0编辑  收藏  举报