P4827 [国家集训队] Crash 的文明世界
题目描述
Solution
看到这种 k k k次幂的式子,就应该往斯特林数的方面想想。
m n = ∑ i { n i } ( n i ) i ! m^n=\sum_i \left\{ \begin{aligned} n \\ i \end{aligned} \right\} \left ( \begin{aligned} n \\ i \end{aligned} \right )i! mn=∑i{ni}(ni)i!
因此
原
式
原式
原式
=
∑
i
,
j
{
k
i
}
(
d
i
s
t
(
i
,
j
)
i
)
i
!
=\sum_{i,j} \left\{ \begin{aligned} k \\ i \end{aligned} \right\} \left ( \begin{aligned} dist(i,j) \\ i \;\;\;\;\;\; \end{aligned} \right )i!
=∑i,j{ki}(dist(i,j)i)i!
=
∑
i
{
k
i
}
i
!
∑
j
(
d
i
s
t
(
i
,
j
)
i
)
=\sum_{i} \left\{ \begin{aligned} k \\ i \end{aligned} \right\}i!\sum_j \left ( \begin{aligned} dist(i,j) \\ i \;\;\;\;\;\; \end{aligned} \right )
=∑i{ki}i!∑j(dist(i,j)i)
=
∑
i
{
k
i
}
i
!
∑
j
(
d
i
s
t
(
i
,
j
)
−
1
i
)
+
∑
j
(
d
i
s
t
(
i
,
j
)
−
1
i
−
1
)
=\sum_{i} \left\{ \begin{aligned} k \\ i \end{aligned} \right\}i!\sum_j \left ( \begin{aligned} dist(i,j)-1 \\ i\;\;\;\;\;\;\;\; \end{aligned} \right )+\sum_j \left ( \begin{aligned} dist(i,j)-1 \\ i-1 \;\;\;\;\;\; \end{aligned} \right )
=∑i{ki}i!∑j(dist(i,j)−1i)+∑j(dist(i,j)−1i−1)
因此设
F
[
x
]
[
k
]
F[x][k]
F[x][k]表示在
x
x
x的子树内,距离
x
x
x为
k
k
k的所有节点的贡献。
有:
F
[
x
]
[
k
]
=
F
[
s
o
n
x
]
[
k
−
1
]
+
F
[
s
o
n
x
]
[
k
]
F[x][k]=F[son_x][k-1]+F[son_x][k]
F[x][k]=F[sonx][k−1]+F[sonx][k]
然后换根
d
p
dp
dp即可。
时间复杂度
O
(
n
k
)
O(nk)
O(nk)。
Code
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <ctime>
#include <cassert>
#include <string.h>
//#include <unordered_set>
//#include <unordered_map>
//#include <bits/stdc++.h>
#define MP(A,B) make_pair(A,B)
#define PB(A) push_back(A)
#define SIZE(A) ((int)A.size())
#define LEN(A) ((int)A.length())
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define fi first
#define se second
using namespace std;
template<typename T>inline bool upmin(T &x,T y) { return y<x?x=y,1:0; }
template<typename T>inline bool upmax(T &x,T y) { return x<y?x=y,1:0; }
typedef long long ll;
typedef unsigned long long ull;
typedef long double lod;
typedef pair<int,int> PR;
typedef vector<int> VI;
const lod eps=1e-11;
const lod pi=acos(-1);
const int oo=1<<30;
const ll loo=1ll<<62;
const int mods=10007;
const int MAXN=100005;
const int INF=0x3f3f3f3f;//1061109567
/*--------------------------------------------------------------------*/
inline int read()
{
int f=1,x=0; char c=getchar();
while (c<'0'||c>'9') { if (c=='-') f=-1; c=getchar(); }
while (c>='0'&&c<='9') { x=(x<<3)+(x<<1)+(c^48); c=getchar(); }
return x*f;
}
vector<int> e[MAXN];
int f[MAXN][155],S[155][155],fac[155],g[155],n,k;
int upd(int x,int y){ return x+y>=mods?x+y-mods:x+y; }
void tree_dp(int x,int father)
{
for (auto v:e[x])
{
if (v==father) continue;
tree_dp(v,x);
}
f[x][0]=1;
for (auto v:e[x])
if (v!=father)
for (int i=0;i<=k;i++)
{
f[x][i]=upd(f[x][i],f[v][i]);
if (i) f[x][i]=upd(f[x][i],f[v][i-1]);
}
}
void dfs(int x,int father)
{
for (auto v:e[x])
{
if (v==father) continue;
for (int i=0;i<=k;i++)
{
g[i]=upd(f[x][i],mods-f[v][i]);
if (i) g[i]=upd(g[i],mods-f[v][i-1]);
}
for (int i=0;i<=k;i++)
{
f[v][i]=upd(f[v][i],g[i]);
if (i) f[v][i]=upd(f[v][i],g[i-1]);
}
dfs(v,x);
}
}
void Init(int k)
{
fac[0]=1;
for (int i=1;i<=k;i++) fac[i]=fac[i-1]*i%mods;
S[0][0]=1;
for (int i=1;i<=k;i++) S[i][i]=S[i][1]=1;
for (int i=1;i<=k;i++)
for (int j=1;j<i;j++) S[i][j]=upd(S[i-1][j-1],S[i-1][j]*j%mods);
}
int main()
{
n=read(),k=read();
for (int i=1;i<n;i++)
{
int u=read(),v=read();
e[u].PB(v);
e[v].PB(u);
}
tree_dp(1,0);
dfs(1,0);
Init(k);
for (int i=1;i<=n;i++)
{
int ans=0;
for (int j=1;j<=k;j++) ans=upd(ans,S[k][j]*fac[j]%mods*f[i][j]%mods);
printf("%d\n",ans);
}
return 0;
}