题目大意
给出一棵 n n n个结点的树以及一个常数 k k k,对于树中的每个结点 v v v,求出:
- 到点 v v v的距离不超过 k k k的点的个数。
- 若点 x x x距离点 v v v不超过 k k k,则 v , x v,x v,x路径上的所有点的权值加 1 1 1。求距离 v v v不超过 k k k的点的权值的乘积。答案对 1 0 9 + 7 10^9+7 109+7取模。
n ⩽ 1 0 5 n\leqslant 10^5 n⩽105, k ⩽ 10 k\leqslant 10 k⩽10。
思路
应该能看出是树形DP。
首先要考虑到贡献的计算。在询问某个点
u
u
u的时候,对于
u
u
u本身,其子树内外的贡献都要计算;对于
u
u
u下方的点,只计算其子树内的贡献;对于
u
u
u子树外的点,只计算其子树外的贡献。因此DP状态分子树内外两种情况讨论。
讨论的时候用 ( u , v ) (u,v) (u,v)表示一条父子边,其中 u u u是父亲。
先解决第一个问题。
f
[
u
]
[
i
]
[
1
]
f[u][i][1]
f[u][i][1]表示点
u
u
u子树内距离
u
u
u不超过
i
i
i的点的个数(包括点
u
u
u本身),
f
[
u
]
[
i
]
[
0
]
f[u][i][0]
f[u][i][0]表示点
u
u
u子树外距离
u
u
u不超过
i
i
i的点的个数(不包括点
u
u
u本身)。
对于
f
[
u
]
[
i
]
[
1
]
f[u][i][1]
f[u][i][1],既然到
u
u
u的距离为
i
i
i,那么到
u
u
u的某个儿子
v
v
v的距离一定是
i
−
1
i-1
i−1,可以累计儿子的贡献,再加上
u
u
u本身,得到第一个方程:
f
[
u
]
[
i
]
[
1
]
=
(
∑
f
[
v
]
[
i
−
1
]
[
1
]
)
+
1
f[u][i][1]=\bigg(\sum f[v][i-1][1]\bigg)+1
f[u][i][1]=(∑f[v][i−1][1])+1
对于
f
[
v
]
[
i
]
[
0
]
f[v][i][0]
f[v][i][0],子树外的点到父亲
u
u
u的距离也一定是
i
−
1
i-1
i−1,并且既可以来自
u
u
u的子树外,也可以来自
u
u
u的其它儿子。既然是其它儿子,就要减去
u
u
u这棵子树的贡献,得到第二个方程:
f
[
v
]
[
i
]
[
0
]
=
f
[
u
]
[
i
−
1
]
[
0
]
+
f
[
u
]
[
i
−
1
]
[
1
]
−
f
[
v
]
[
i
−
2
]
[
1
]
f[v][i][0]=f[u][i-1][0]+f[u][i-1][1]-f[v][i-2][1]
f[v][i][0]=f[u][i−1][0]+f[u][i−1][1]−f[v][i−2][1]
最终答案为每个结点子树内外的贡献之和,由于结点本身的贡献只在子树内被计算,不需要去重。不难发现这个答案就是第二个问题中的点权。
a
n
s
1
[
u
]
=
f
[
u
]
[
k
]
[
0
]
+
f
[
u
]
[
k
]
[
1
]
ans_1[u]=f[u][k][0]+f[u][k][1]
ans1[u]=f[u][k][0]+f[u][k][1]
然后是第二个问题。
g [ u ] [ i ] [ 1 ] g[u][i][1] g[u][i][1]表示点 u u u子树内距离 u u u不超过 i i i的点(包括点 u u u本身)在到达点 u u u的路径上对经过的点的权值加 1 1 1后,点 u u u子树内距离 u u u不超过 i i i的点的权值的乘积。 g [ u ] [ i ] [ 0 ] g[u][i][0] g[u][i][0]的含义同理,就不费口舌叙述了。
对于
g
[
u
]
[
i
]
[
1
]
g[u][i][1]
g[u][i][1],即点
u
u
u子树内的点,同样可以累计儿子的贡献,再乘上点
u
u
u本身的权值。点
u
u
u子树内能到达点
u
u
u的点一共有
f
[
u
]
[
i
]
[
1
]
f[u][i][1]
f[u][i][1]个,每一个点都会对点
u
u
u的权值加
1
1
1,因此点
u
u
u的权值就为
f
[
u
]
[
i
]
[
1
]
f[u][i][1]
f[u][i][1],得到第三个方程:
g
[
u
]
[
i
]
[
1
]
=
(
∏
g
[
v
]
[
i
−
1
]
[
1
]
)
⋅
f
[
u
]
[
i
]
[
1
]
g[u][i][1]=\bigg(\prod g[v][i-1][1]\bigg)\cdot f[u][i][1]
g[u][i][1]=(∏g[v][i−1][1])⋅f[u][i][1]
对于
g
[
v
]
[
i
]
[
0
]
g[v][i][0]
g[v][i][0],即点
v
v
v子树外的点,同样可以先到父亲
u
u
u,累计
u
u
u的贡献,再除去
v
v
v这棵子树的贡献,得到第四个方程:
g
[
v
]
[
i
]
[
0
]
=
g
[
u
]
[
i
−
1
]
[
0
]
⋅
g
[
u
]
]
[
i
−
1
]
[
1
]
g
[
v
]
[
i
−
2
]
[
1
]
g[v][i][0]=\frac{g[u][i-1][0]\cdot g[u]][i-1][1]}{g[v][i-2][1]}
g[v][i][0]=g[v][i−2][1]g[u][i−1][0]⋅g[u]][i−1][1]
如果你列出的方程是上面这个样子,你就完了。
第四个方程有非常严重的错误。我们试图用
g
[
u
]
[
i
−
1
]
[
0
]
⋅
g
[
u
]
[
i
−
1
]
[
1
]
g[u][i-1][0]\cdot g[u][i-1][1]
g[u][i−1][0]⋅g[u][i−1][1]计算所有距离
u
u
u不超过
i
−
1
i-1
i−1的点到达点
u
u
u后产生的点权的乘积,显然子树内外的贡献都要计算。但此时点
u
u
u的点权被拆成了两部分:来自子树内的
f
[
u
]
[
i
−
1
]
[
1
]
f[u][i-1][1]
f[u][i−1][1]和来自子树外的
f
[
u
]
[
i
−
1
]
[
0
]
f[u][i-1][0]
f[u][i−1][0]。首先
g
[
u
]
[
i
−
1
]
[
0
]
g[u][i-1][0]
g[u][i−1][0]根本就不包含点
u
u
u来自子树外的贡献
f
[
u
]
[
i
−
1
]
[
0
]
f[u][i-1][0]
f[u][i−1][0];即使
g
[
u
]
[
i
−
1
]
[
0
]
g[u][i-1][0]
g[u][i−1][0]包含了
f
[
u
]
[
i
−
1
]
[
0
]
f[u][i-1][0]
f[u][i−1][0],上面的方程也是把点
u
u
u的两部分权值相乘,但是显然这两部分应该是相加的关系。(不清楚的可以手动模拟)
于是这个方程中点
u
u
u的权值是错误的。由于我们知道这个错误的权值是
f
[
u
]
[
i
−
1
]
[
1
]
f[u][i-1][1]
f[u][i−1][1],可以把这个错误的权值除掉,把正确的权值乘上去,注意仍然要减去点
v
v
v这棵子树的贡献。
g
[
v
]
[
i
]
[
0
]
=
g
[
u
]
[
i
−
1
]
[
0
]
⋅
g
[
u
]
]
[
i
−
1
]
[
1
]
g
[
v
]
[
i
−
2
]
[
1
]
⋅
f
[
u
]
[
i
−
1
]
[
0
]
+
f
[
u
]
[
i
−
1
]
[
1
]
−
f
[
v
]
[
i
−
2
]
[
1
]
f
[
u
]
[
i
−
1
]
[
1
]
=
g
[
u
]
[
i
−
1
]
[
0
]
⋅
g
[
u
]
]
[
i
−
1
]
[
1
]
g
[
v
]
[
i
−
2
]
[
1
]
⋅
f
[
v
]
[
i
]
[
0
]
f
[
u
]
[
i
−
1
]
[
1
]
\begin{aligned} g[v][i][0]&=\frac{g[u][i-1][0]\cdot g[u]][i-1][1]}{g[v][i-2][1]}\cdot\frac{f[u][i-1][0]+f[u][i-1][1]-f[v][i-2][1]}{f[u][i-1][1]}\\ &=\frac{g[u][i-1][0]\cdot g[u]][i-1][1]}{g[v][i-2][1]}\cdot\frac{f[v][i][0]}{f[u][i-1][1]} \end{aligned}
g[v][i][0]=g[v][i−2][1]g[u][i−1][0]⋅g[u]][i−1][1]⋅f[u][i−1][1]f[u][i−1][0]+f[u][i−1][1]−f[v][i−2][1]=g[v][i−2][1]g[u][i−1][0]⋅g[u]][i−1][1]⋅f[u][i−1][1]f[v][i][0]
同理,最终统计答案的时候也不能直接把子树内外的贡献相乘了,还是需要先把错误的权值除掉,乘上正确的权值。
a
n
s
2
[
u
]
=
g
[
u
]
[
k
]
[
0
]
⋅
g
[
u
]
[
k
]
[
1
]
⋅
f
[
u
]
[
i
−
1
]
[
0
]
+
f
[
u
]
[
i
−
1
]
[
1
]
f
[
u
]
[
i
−
1
]
[
1
]
ans_2[u]=g[u][k][0]\cdot g[u][k][1]\cdot\frac{f[u][i-1][0]+f[u][i-1][1]}{f[u][i-1][1]}
ans2[u]=g[u][k][0]⋅g[u][k][1]⋅f[u][i−1][1]f[u][i−1][0]+f[u][i−1][1]