传送门
题意:
给一棵树,边权为 1,对于每个点 i,输出
∑
j
=
1
n
d
i
s
(
i
,
j
)
m
,
n
≤
50000
,
m
≤
500
∑_{j=1}^ndis(i, j)^m,n ≤ 50000, m ≤ 500
∑j=1ndis(i,j)m,n≤50000,m≤500
思路:
考虑对所有的
i
∈
[
0
,
m
]
i\in[0,m]
i∈[0,m]维护
∑
d
i
s
i
‾
\sum dis^{\underline i}
∑disi。
然后要用到一个下降幂之间的转化:
(
x
+
1
)
i
‾
=
x
i
‾
+
i
x
i
−
1
‾
(x+1)^{\underline i}=x^{\underline i}+ix^{\underline{i-1}}
(x+1)i=xi+ixi−1
于是对于一个点
p
p
p:
A
n
s
p
=
∑
v
=
1
n
d
i
s
p
,
v
m
Ans_p=\sum_{v=1}^ndis_{p,v}^m
Ansp=v=1∑ndisp,vm
=
∑
v
=
1
n
∑
i
=
0
m
S
m
i
d
i
s
p
,
v
i
‾
=\sum_{v=1}^n\sum_{i=0}^mS_{m}^idis_{p,v}^{\underline i}
=v=1∑ni=0∑mSmidisp,vi
=
∑
i
=
0
m
i
!
S
m
i
∑
v
=
1
n
C
d
i
s
p
,
v
i
=\sum_{i=0}^mi!S_{m}^i\sum_{v=1}^nC_{dis_{p,v}}^{i}
=i=0∑mi!Smiv=1∑nCdisp,vi
然后发现我们学过组合恒等式
C
d
i
s
p
,
v
i
=
C
d
i
s
p
,
v
−
1
i
+
C
d
i
s
p
,
v
−
1
i
−
1
C_{dis_{p,v}}^{i}=C_{dis_{p,v}-1}^{i}+C_{dis_{p,v}-1}^{i-1}
Cdisp,vi=Cdisp,v−1i+Cdisp,v−1i−1。
于是就可以树形
d
p
dp
dp啦。
维护两个数组
f
,
g
f,g
f,g。
f
p
,
i
f_{p,i}
fp,i表示
p
p
p子树里所有点到自己的距离对应的
C
d
i
s
p
,
v
i
C_{dis_{p,v}}^{i}
Cdisp,vi之和。
g
p
,
i
g_{p,i}
gp,i表示
p
p
p子树外所有点到自己的距离对应的
C
d
i
s
p
,
v
i
C_{dis_{p,v}}^{i}
Cdisp,vi之和。
然后随便转一转就能转出来。
代码:
#include<bits/stdc++.h>
#define ri register int
using namespace std;
const int rlen=1<<18|1;
inline char gc(){
static char buf[rlen],*ib,*ob;
(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
return ib==ob?-1:*ib++;
}
inline int read(){
int ans=0;
char ch=gc();
while(!isdigit(ch))ch=gc();
while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
return ans;
}
typedef long long ll;
const int mod=10007;
inline int add(const int&a,const int&b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(const int&a,const int&b){return a>=b?a-b:a-b+mod;}
inline int mul(const int&a,const int&b){return (ll)a*b%mod;}
inline void Add(int&a,const int&b){a=a+b>=mod?a+b-mod:a+b;}
inline void Dec(int&a,const int&b){a=a>=b?a-b:a-b+mod;}
inline void Mul(int&a,const int&b){a=(ll)a*b%mod;}
const int N=50005,K=155;
vector<int>e[N];
int n,k,f[N][K],g[N][K],fac[K],S[K][K];
void dfs1(int p,int fa){
f[p][0]=1;
for(ri i=0,v;i<e[p].size();++i){
if((v=e[p][i])==fa)continue;
dfs1(v,p);
for(ri j=0;j<=k;++j){
Add(f[p][j],f[v][j]);
if(j)Add(f[p][j],f[v][j-1]);
}
}
}
void dfs2(int p,int fa){
for(ri i=0,v;i<e[p].size();++i){
if((v=e[p][i])==fa)continue;
for(ri j=0;j<=k;++j){
Add(g[v][j],add(g[p][j],f[p][j]));
if(j)Add(g[v][j],add(g[p][j-1],f[p][j-1]));
Dec(g[v][j],f[v][j]);
if(j)Dec(g[v][j],add(f[v][j-1],f[v][j-1]));
if(j>1)Dec(g[v][j],f[v][j-2]);
}
dfs2(v,p);
}
}
inline void init(int up){
fac[0]=fac[1]=1;
for(ri i=2;i<=up;++i)fac[i]=mul(i,fac[i-1]);
S[0][0]=1;
for(ri i=1;i<=up;++i)for(ri j=1;j<=i;++j)S[i][j]=add(S[i-1][j-1],mul(S[i-1][j],j));
}
int main(){
n=read(),k=read();
init(k);
int L=read(),now=read(),A=read(),B=read(),Q=read();
for(ri t,i=1,u,v;i<n;++i){
now=(now*A+B)%Q;
t=i<L?i:L;
u=i-now%t,v=i+1;
e[u].push_back(v),e[v].push_back(u);
}
dfs1(1,0),dfs2(1,0);
for(ri t=0,p=1;p<=n;++p,t=0){
for(ri i=0;i<=k;++i)Add(t,mul(add(f[p][i],g[p][i]),mul(fac[i],S[k][i])));
cout<<t<<'\n';
}
return 0;
}