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 }

猜你喜欢

转载自www.cnblogs.com/Menhera/p/9093211.html