Luogu4827 Crash的文明世界
Luogu4827 Crash的文明世界
题面:Luogu
解析
很久以前做的题了,今天重新推一遍。
\[S(i)=\sum_{j=1}^{n} dist(i,j)^k
\]
\[=\sum_{j=1}^{n} \sum_{t=0}^{k} S(k,t) \times t! \times { dist(i,j) \choose t }
\]
\[=\sum_{t=0}^{k} S(k,t) \times t! \times \sum_{j=1}^{n} { dist(i,j) \choose t}
\]
设\(f(i,j)=\sum_{k=1}^{n} { dist(i,k) \choose j }\),那么\(S(i)=\sum_{t=0}^{k} S(k,t) \times t! \times f(i,t)\),现在考虑如何求\(f(i,j)\)。
观察到有\({dist(i,j) \choose k}={dist(i,j)-1 \choose k-1}+{dist(i,j)-1 \choose k}\),
这启迪我们对于一个点,可以先计算子树内的贡献。
不妨设\(g_1(i,j)\)表示子树内的贡献,\(g_2(i,j)\)表示子树外的贡献,
由上式知\(g_1(i,j)=\sum_{v \subseteq i.son} g_1(v,j-1)+g_1(v,j)(j\gt0)\),
这样我们就计算了子树内的贡献。
那么如何解决子树外的贡献呢?
仍然利用上面的思路,从上往下计算,
令\(tmp(v,j)=g_1(u,j)-g_1(v,j)-g_1(v,j-1)\),
那么有\(g_2(v,j)=tmp(v,j)+tmp(v,j-1)+g_2(u,j-1)+g_2(u,j)\),
最后即可\(O(nk)\)得到\(f(i,j)\)。
代码
// luogu-judger-enable-o2
#include<cstdio>
#define N 50005
using namespace std;
const int P=1e4+7;
inline int In(){
char c=getchar(); int x=0,ft=1;
for(;c<'0'||c>'9';c=getchar()) if(c=='-') ft=-1;
for(;c>='0'&&c<='9';c=getchar()) x=x*10+c-'0';
return x*ft;
}
int n,K,h[N],e_tot=0,ans;
struct E{ int to,nex; }e[N<<1];
inline void add(int u,int v){
e[++e_tot]=(E){v,h[u]}; h[u]=e_tot;
}
int S[155][155],fac[155];
inline void Get_S_fac(){
fac[0]=1; for(int i=1;i<=K;++i) fac[i]=1ll*i*fac[i-1]%P;
S[0][0]=1;
for(int i=1;i<=K;++i)
for(int j=1;j<=K;++j)
S[i][j]=(S[i-1][j-1]+1ll*j*S[i-1][j]%P)%P;
}
int g1[N][155],g2[N][155],tmp[155];
void dfs1(int u,int pre){
g1[u][0]=1;
for(int i=h[u],v;i;i=e[i].nex){
if((v=e[i].to)==pre) continue; dfs1(v,u);
g1[u][0]=(g1[u][0]+g1[v][0])%P;
for(int j=1;j<=K;++j)
g1[u][j]=(g1[u][j]+(g1[v][j-1]+g1[v][j])%P)%P;
}
}
void dfs2(int u,int pre){
for(int i=h[u],v;i;i=e[i].nex){
if((v=e[i].to)==pre) continue;
tmp[0]=(g1[u][0]-g1[v][0]+P)%P;
for(int j=1;j<=K;++j)
tmp[j]=((g1[u][j]-g1[v][j-1]+P)%P-g1[v][j]+P)%P;
g2[v][0]=tmp[0];
for(int j=1;j<=K;++j) g2[v][j]=(tmp[j-1]+tmp[j])%P;
g2[v][0]=(g2[u][0]+g2[v][0])%P;
for(int j=1;j<=K;++j)
g2[v][j]=(g2[v][j]+(g2[u][j-1]+g2[u][j])%P)%P;
dfs2(v,u);
}
}
int main(){
n=In(); K=In(); Get_S_fac();
for(int i=1,u,v;i<n;++i){
u=In(); v=In();
add(u,v); add(v,u);
}
dfs1(1,-1); dfs2(1,-1);
for(int i=1;i<=n;++i){
ans=0;
for(int t=0;t<=K;++t)
ans=(ans+1ll*(g1[i][t]+g2[i][t])%P*S[K][t]*fac[t]%P)%P;
printf("%d\n",ans);
}
return 0;
}