题意:
分析:
- 前置芝士:第二类斯特林数
我们先写出答案的式子
(displaystyle S(i)=sum_{j=1}^ndis(i,j)^k)
我们按照是否在子树内进行分类一下,而且我们发现似乎没有办法直接统计 (k) 次方,很容易想到第二类斯特林数可以优化 (k) 次方的和
[S(i)=sum_{d=0}^kd!S_k^dsum_jC_{dis(i,j)}^d
\
=sum_{d=0}^kd!S_k^d(sum_{jin i}C_{dis(j,i)}^d+sum_{j
otin i}C_{dis(i,j)}^d)
]
然后我们记括号里第一个式子为 (dp1[i][d]) 第二个式子为 (dp2[i][d])
子树内的答案很好统计所以我们先来推一下 (dp1)
[dp1[i][d]=sum_{jin i} C_{dis(i,j)}^d
\
=[d==0]+sum_{vand fa[v]==i} sum_{jin v} C_{dis(v,j)+1}^d
\
=[d==0]+sum_{vand fa[v]==i}sum_{jin v}(C_{dis(v,j)}^d+C_{dis(v,j)}^{d-1})
\
=[d==0]+sum_{vand fa[v]==i}(dp1[v][j]+dp1[v][j-1])
]
接下来要统计子树外的答案
[dp2[i][d]=sum_{j
otin i}C_{dis(i,j)}^d
\
=sum_{j
otin fa}C_{dis(fa,j)+1}^d+sum_{jin fa} C_{dis(fa,j)+1}^d-sum_{jin i}C_{dis(i,j)+2}^d
\
=(dp2[fa][d]+dp2[fa][d-1])+(dp1[fa][d]+dp1[fa][d-1])-(dp1[i][d]+2*dp[i][d-1]+dp[i][d-2])
]
其中 (dp2[1][d]) 恒等于 (0)
直接换根 DP
代码:
#include<bits/stdc++.h>
#define inl inline
#define reg register
#define pb push_back
using namespace std;
namespace zzc
{
typedef long long ll;
inl int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
const int maxn = 5e4+5;
const int maxk = 200;
const ll mod = 10007;
ll s[maxk][maxk],fac[maxk],dp1[maxn][maxk],dp2[maxn][maxk];
ll n,k;
vector<int> e[maxn];
void init()
{
s[0][0]=1;
for(reg ll i=1;i<=150;i++) for(reg ll j=1;j<=i;j++) s[i][j]=(s[i-1][j-1]+s[i-1][j]*j%mod)%mod;
fac[0]=1;
for(reg ll i=1;i<=150;i++) fac[i]=fac[i-1]*i%mod;
}
void dfs1(int u,int ff)
{
dp1[u][0]=1;
for(auto v:e[u])
{
if(v==ff) continue;
dfs1(v,u);
dp1[u][0]=(dp1[u][0]+dp1[v][0])%mod;
for(reg int i=1;i<=k;i++) dp1[u][i]=(dp1[u][i]+dp1[v][i]+dp1[v][i-1])%mod;
}
}
void dfs2(int u,int ff)
{
if(u!=1)
{
dp2[u][0]=(dp2[ff][0]+dp1[ff][0]-dp1[u][0]+mod)%mod;
dp2[u][1]=(dp2[ff][1]+dp2[ff][0]+dp1[ff][1]+dp1[ff][0]-dp1[u][1]-2*dp1[u][0]+3*mod)%mod;
for(reg int i=2;i<=k;i++) dp2[u][i]=( (dp2[ff][i]+dp2[ff][i-1])%mod + (dp1[ff][i]+dp1[ff][i-1])%mod -(dp1[u][i]+2*dp1[u][i-1]+dp1[u][i-2])%mod + mod)%mod;
}
for(auto v:e[u]) if(v!=ff) dfs2(v,u);
}
void work()
{
int a,b;
init();
n=read();k=read();
for(reg int i=1;i<n;i++)
{
a=read();b=read();
e[a].pb(b);e[b].pb(a);
}
dfs1(1,0);dfs2(1,0);
for(reg int i=1;i<=n;i++)
{
ll ans=0;
for(reg int d=0;d<=k;d++) ans=(ans+fac[d]*s[k][d]%mod*(dp1[i][d]+dp2[i][d])%mod)%mod;
printf("%lld
",ans);
}
}
}
int main()
{
zzc::work();
return 0;
}