题目大意:
给你一棵
n
n
n个点的树,边权都为1。
对于每一个点
i
i
i,
s
(
i
)
=
∑
j
=
1
n
d
i
s
(
i
,
j
)
k
s(i)=\sum_{j=1}^{n}dis(i,j)^k
s(i)=∑j=1ndis(i,j)k。
其中
k
k
k给定常数,求所有点的s值。
n
≤
50000
,
k
≤
150
n≤50000,k≤150
n≤50000,k≤150
分析:
根据斯特林数的一个性质,
m
n
=
∑
i
=
1
m
S
(
n
,
i
)
∗
P
(
m
,
i
)
m^n=\sum_{i=1}^{m}S(n,i)*P(m,i)
mn=∑i=1mS(n,i)∗P(m,i)
其中,
S
S
S表示第二类斯特林数,
P
P
P表示排列数。
证明:考虑把
n
n
n个有区别的小球放入
m
m
m个有区别的盒子,求方案数。
把
n
n
n个小球放入
i
i
i个无区别的盒子,且不为空的方案数为
S
(
n
,
i
)
S(n,i)
S(n,i)。
我们枚举有小球的盒子数
i
i
i,再从
m
m
m个盒子中选出
i
i
i个。因为盒子有区别,所以乘排列数。
即方案为
∑
i
=
1
m
S
(
n
,
i
)
∗
P
(
m
,
i
)
\sum_{i=1}^{m}S(n,i)*P(m,i)
∑i=1mS(n,i)∗P(m,i)。
显然每个小球有
m
m
m种选择,方案数表示为
m
n
m^n
mn。
所以上式成立。
题目中的
s
s
s可以表示成,
s
(
i
)
=
∑
j
=
1
n
∑
k
=
1
m
S
(
m
,
k
)
∗
P
(
d
i
s
(
i
,
j
)
,
k
)
s(i)=\sum_{j=1}^{n}\sum_{k=1}^{m}S(m,k)*P(dis(i,j),k)
s(i)=∑j=1n∑k=1mS(m,k)∗P(dis(i,j),k)
=
∑
k
=
1
m
S
(
m
,
k
)
∑
j
=
1
n
P
(
d
i
s
(
i
,
j
)
,
k
)
=\sum_{k=1}^{m}S(m,k)\sum_{j=1}^{n}P(dis(i,j),k)
=∑k=1mS(m,k)∑j=1nP(dis(i,j),k)
=
∑
k
=
1
m
S
(
m
,
k
)
∗
k
!
∑
j
=
1
n
C
(
d
i
s
(
i
,
j
)
,
k
)
=\sum_{k=1}^{m}S(m,k)*k!\sum_{j=1}^{n}C(dis(i,j),k)
=∑k=1mS(m,k)∗k!∑j=1nC(dis(i,j),k)
关键求
T
(
i
)
=
∑
j
=
1
n
C
(
d
i
s
(
i
,
j
)
,
k
)
T(i)=\sum_{j=1}^{n}C(dis(i,j),k)
T(i)=∑j=1nC(dis(i,j),k)。
设
f
[
i
]
[
j
]
f[i][j]
f[i][j]表示
i
i
i的子树内的点到
i
i
i,当
k
=
j
k=j
k=j的
T
T
T值和;
g
[
i
]
[
j
]
g[i][j]
g[i][j]表示
i
i
i的子树外的点到
i
i
i,当
k
=
j
k=j
k=j的
T
T
T值和。
对于
f
f
f,考虑
x
x
x的一个儿子
y
y
y,因为这条边长为1,所以子树内所有的
d
i
s
dis
dis都要加1。
f
[
x
]
[
j
]
+
=
f
[
y
]
[
j
]
+
f
[
y
]
[
j
−
1
]
f[x][j]+=f[y][j]+f[y][j-1]
f[x][j]+=f[y][j]+f[y][j−1]
对于
g
g
g,首先他的父亲的所有点
d
i
s
dis
dis加1,即
g
[
x
]
[
j
]
+
=
g
[
f
a
]
[
j
]
+
g
[
f
a
]
[
j
−
1
]
g[x][j]+=g[fa][j]+g[fa][j-1]
g[x][j]+=g[fa][j]+g[fa][j−1]
他的兄弟到他的距离也要加1,可以看出整棵fa的子树减去当前子树,即
g
[
x
]
[
j
]
+
=
f
[
f
a
]
[
j
]
+
f
[
f
a
]
[
j
−
1
]
g[x][j]+=f[fa][j]+f[fa][j-1]
g[x][j]+=f[fa][j]+f[fa][j−1]
而
f
[
f
a
]
[
j
]
f[fa][j]
f[fa][j]和
f
[
f
a
]
[
j
−
1
]
f[fa][j-1]
f[fa][j−1]都加多了,分别减去。
g
[
x
]
[
j
]
−
=
f
[
x
]
[
j
]
+
f
[
x
]
[
j
−
1
]
g[x][j]-=f[x][j]+f[x][j-1]
g[x][j]−=f[x][j]+f[x][j−1]
g
[
x
]
[
j
]
−
=
f
[
x
]
[
j
−
1
]
+
f
[
x
]
[
j
−
2
]
g[x][j]-=f[x][j-1]+f[x][j-2]
g[x][j]−=f[x][j−1]+f[x][j−2]
代码:
/**************************************************************
Problem: 2159
User: ypxrain
Language: C++
Result: Accepted
Time:4792 ms
Memory:65584 kb
****************************************************************/
#include <iostream>
#include <cstdio>
#include <cmath>
const int maxn=5e4+7;
const int mod=10007;
using namespace std;
int n,m,x,y,cnt,ans;
int L,now,A,B,Q;
int f[maxn][157],g[maxn][157],ls[maxn],s[157][157],jc[157];
struct edge{
int y,next;
}e[maxn*2];
void add(int x,int y)
{
e[++cnt]=(edge){y,ls[x]};
ls[x]=cnt;
}
void dfs1(int x,int fa)
{
f[x][0]=1;
for (int i=ls[x];i>0;i=e[i].next)
{
int y=e[i].y;
if (y==fa) continue;
dfs1(y,x);
f[x][0]=(f[x][0]+f[y][0])%mod;
for (int j=1;j<=m;j++) f[x][j]=(f[x][j]+f[y][j]+f[y][j-1])%mod;
}
}
void dfs2(int x,int fa)
{
if (fa)
{
g[x][0]=n-f[x][0];
for (int j=1;j<=m;j++)
{
g[x][j]=(g[x][j]+g[fa][j]+g[fa][j-1])%mod;
g[x][j]=(g[x][j]+f[fa][j]+f[fa][j-1])%mod;
g[x][j]=(g[x][j]+2*mod-f[x][j]-f[x][j-1])%mod;
if (j>1) g[x][j]=(g[x][j]+2*mod-f[x][j-1]-f[x][j-2])%mod;
else g[x][j]=(g[x][j]+mod-f[x][j-1])%mod;
}
}
for (int i=ls[x];i>0;i=e[i].next)
{
int y=e[i].y;
if (y==fa) continue;
dfs2(y,x);
}
}
int main()
{
scanf("%d%d%d%d%d%d%d",&n,&m,&L,&now,&A,&B,&Q);
for (int i=1;i<n;i++){
now=(now*A+B)%Q;
int tmp=i<L?i:L;
int x=i-now%tmp,y=i+1;
add(x,y);
add(y,x);
}
s[0][0]=jc[0]=1;
for (int i=1;i<=m;i++)
{
jc[i]=jc[i-1]*i%mod;
for (int j=1;j<=i;j++) s[i][j]=(s[i-1][j]*j%mod+s[i-1][j-1])%mod;
}
dfs1(1,0);
dfs2(1,0);
for (int i=1;i<=n;i++)
{
int ans=0;
for (int j=1;j<=m;j++) ans=(ans+s[m][j]*jc[j]%mod*(f[i][j]+g[i][j])%mod)%mod;
printf("%d\n",ans);
}
}