您的位置:首页 > 其它

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

2018-08-29 18:03 337 查看

题意:给定一棵树,求$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得到答案。

#include<cstdio>
#include<algorithm>
#define rep(i,l,r) for (int i=(l); i<=(r); i++)
#define For(i,x) for (int i=h[x],k; i; i=nxt[i])
using namespace std;

const int N=50010,K=160,mod=10007;
int n,m,l,u,v,now,cnt,A,B,Q,tmp,p
,f
[K],S[K][K],fac[K],ans
;
int to[N<<1],nxt[N<<1],h
;
void add(int u,int v){ to[++cnt]=v; nxt[cnt]=h[u]; h[u]=cnt; }

void dfs(int x,int fa){
f[x][0]=1;
For(i,x) if ((k=to[i])!=fa){
dfs(k,x); f[x][0]=(f[x][0]+f[k][0])%mod;
rep(j,1,m) f[x][j]=(f[x][j]+f[k][j]+f[k][j-1])%mod;
}
}

void getans(int x,int fa){
rep(i,0,m) ans[x]=(ans[x]+f[x][i]*fac[i]%mod*S[m][i])%mod;
For(i,x) if ((k=to[i])!=fa){
for (int j=m; j>=2; j--)
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;
f[k][1]=((f[x][1]-f[k][0]+f[x][0]-f[k][0])%mod+mod)%mod; f[k][0]=n;
getans(k,x);
}
}

int main(){
scanf("%d%d",&n,&m);
rep(i,1,n-1) scanf("%d%d",&u,&v),add(u,v),add(v,u);
dfs(1,1);
fac[0]=1; rep(i,1,m) fac[i]=fac[i-1]*i%mod;
S[0][0]=1;
rep(i,1,m) rep(j,1,i) S[i][j]=(S[i-1][j-1]+S[i-1][j]*j)%mod;
getans(1,1);
rep(i,1,n) printf("%d\n",ans[i]);
return 0;
}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: