HDU4625 JZPTREE 【树形DP】【第二类斯特林数】
题目大意:
对1到n求题目中描述的那个式子。
题目分析:
幂不好处理,转化为斯特林数。
根据$ n^k= \sum_ { i=0 }^k S(k,i)×i!×C(n,i) $。
我们可以将问题转化为对每个u和$ j=1 \sim k $求$ \sum_ { i=1 }^n \binom{dist(u,i)}{j} $。 通过杨辉三角向子树做一遍树形DP,再向父亲做一遍树形DP即可。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const int mod = 10007; 5 6 int n,k; 7 8 int S[505][505]; 9 int f[50005][505]; 10 int fac[505]; 11 vector <int> g[50005]; 12 13 void init(){ 14 memset(f,0,sizeof(f)); 15 } 16 17 void read(){ 18 scanf("%d%d",&n,&k); 19 for(int i=1;i<=n;i++) g[i].clear(); 20 for(int i=1;i<n;i++){ 21 int u,v; scanf("%d%d",&u,&v); 22 g[u].push_back(v); g[v].push_back(u); 23 } 24 } 25 26 void dfs1(int now,int fa){ 27 for(int i=0;i<g[now].size();i++){ 28 if(g[now][i] == fa) continue; 29 dfs1(g[now][i],now); 30 f[now][0] += f[g[now][i]][0]; 31 f[now][0] %= mod; 32 for(int j=1;j<=k;j++){ 33 f[now][j] += f[g[now][i]][j] + f[g[now][i]][j-1]; 34 f[now][j] %= mod; 35 } 36 } 37 f[now][0] ++; 38 } 39 40 void dfs2(int now,int fa){ 41 for(int i=0;i<g[now].size();i++){ 42 if(g[now][i] == fa) continue; 43 for(int j=k;j>=1;j--){ 44 int p = f[now][j]-f[g[now][i]][j]-f[g[now][i]][j-1]; 45 p = ((p%mod)+mod)%mod; 46 int q=f[now][j-1]-f[g[now][i]][j-1]-(j-2>=0?f[g[now][i]][j-2]:0); 47 q = ((q%mod)+mod)%mod; 48 f[g[now][i]][j] += p+q; 49 f[g[now][i]][j] %= mod; 50 } 51 f[g[now][i]][0] += f[now][0] - f[g[now][i]][0]; 52 f[g[now][i]][0] %= mod; 53 dfs2(g[now][i],now); 54 } 55 } 56 57 void work(){ 58 dfs1(1,0); 59 dfs2(1,0); 60 for(int i=1;i<=n;i++){ 61 int ans = 0; 62 for(int j=0;j<=k;j++){ 63 int nowans = (((fac[j]*f[i][j])%mod)*S[k][j])%mod; 64 ans += nowans; ans %= mod; 65 } 66 printf("%d\n",ans); 67 } 68 } 69 70 int main(){ 71 int t; scanf("%d",&t); 72 fac[0] = 1; 73 for(int i=1;i<=500;i++) S[i][1] = 1,fac[i] = (fac[i-1]*i)%mod; 74 for(int i=1;i<=500;i++){ 75 for(int j=2;j<=i;j++) S[i][j] = (S[i-1][j-1]+j*S[i-1][j])%mod; 76 } 77 while(t--){ 78 init(); 79 read(); 80 work(); 81 } 82 return 0; 83 }