题目传送门
还是翻译:
题目描述
我们都知道,Rikka酱数学不好,勇太君担心这个情况,所以他给了六花同学一些数学题来练习,下面是其中的一道:
勇太桑有一棵有 n n n个节点的树,树上的所有边长度都是 1 1 1,对于这些点的一个非空子集 S S S, S S S的价值 value ( S ) \text{value}(S) value(S)等于 max ( dis ( u , v ) ) \max(\text{dis}(u,v)) max(dis(u,v)),其中 u , v ∈ S u,v\in S u,v∈S, dis ( u , v ) \text{dis}(u,v) dis(u,v)表示 u , v u,v u,v两点间距离。
容易发现, value ( S ) ∈ [ 0 , n ) \text{value}(S)\in[0,n) value(S)∈[0,n)。现在,对于 ∀ K ∈ [ 0 , n ) \forall K\in [0,n) ∀K∈[0,n),勇太君想知道有多少 S S S集合满足 value ( S ) = K \text{value}(S)=K value(S)=K。
这对于六花酱来说太难了,你能帮帮她吗?
输入 Input
第一行包含一个整数 t ( 1 ≤ t ≤ 100 ) t(1\le t\le 100) t(1≤t≤100),表示测试数据组数,并有不超过 5 5 5组数据 n > 100 n>100 n>100。
对于每组测试数据,第一行一个正整数 n ( 1 ≤ n ≤ 3000 ) n(1\le n\le 3000) n(1≤n≤3000),接下来的 n − 1 n-1 n−1行,每行两个数 u , v u,v u,v,表示 u u u与 v v v之间有一条边。
输出 Output
对于每组测试数据,输出一行 n n n个数,第 i i i个数表示满足 value ( S ) = i − 1 \text{value}(S)=i-1 value(S)=i−1的非空集合个数,这个答案可能很大,所以输出答案模 998244353 998244353 998244353.
我们知道,Rikka with Subset这道题是NTT,这道题应该不是。
(我就是闲的没事来看看……)
注意,选择
x
x
x个点,这
x
x
x个点未必连通。
好了怎么做?
暴力一点,枚举集合,一共
2
n
−
1
2^n-1
2n−1个,然后找到树上最长的路径,这样总复杂度是
O
(
n
2
n
)
O(n2^n)
O(n2n)的……
(摔西瓜……)
现在换种思路,如果我们枚举所选集合中最长路径,然后往里加点不就好了,这样就是
O
(
n
2
)
O(n^2)
O(n2)的了。
如果我们确定了两个端点,那么这两个端点之间的点(只是在路径上)是随意加的,如果两点间距离为
k
k
k,那么这样的方案数共有
2
k
−
1
2^{k-1}
2k−1种。
诶诶诶不对啊,我怎么少了这么多种?
不在路径上的点也可以进入集合并且不影响最长路径!
如图所示的一棵树,如果选择了端点
(
7
,
9
)
(7,9)
(7,9),则
5
,
8
,
10
5,8,10
5,8,10也可以进入集合。
这样枚举就不行了,我们还得沿着路径爬上去计算选择子树的情况……这样就是
O
(
n
3
)
O(n^3)
O(n3)的了。
我们换种方法,枚举中间点来消除子树对最长路径的影响。
诶中间点?如果中间是条边怎么办?
分情况讨论……
我们需要预处理出一个点向下
j
(
0
≤
j
≤
n
2
)
j(0\le j\le \frac{n}{2})
j(0≤j≤2n)层的节点数,还要预处理出到一个点距离为
j
(
0
≤
j
≤
n
2
)
j(0\le j\le \frac{n}{2})
j(0≤j≤2n)的节点数。第一个好办,一遍树DP即可,第二个……
得了直接BFS吧(flag)
好了我们知道了这些,然后就是统计答案了……
对于一个点
x
x
x,如果他是这条路径的中点,我们可以知道这条路径两端位于距离
x
x
x相等的位置上(如上图树中
(
4
,
6
)
(4,6)
(4,6),
1
1
1为中点),于是我们枚举一半的距离
dis
∈
[
1
,
n
2
]
\text{dis}\in[1,\frac{n}{2}]
dis∈[1,2n],如果距
x
x
x距离为
dis
\text{dis}
dis上点数少于
2
2
2,就可以停止枚举了,如果有,那么
2
dis
2\text{dis}
2dis距离的答案就可以加了……
加多少?
我们一定是从一个小的
dis
\text{dis}
dis扩展到一个大的
dis
\text{dis}
dis,那么小的
dis
\text{dis}
dis中的点都可以加到大的
dis
\text{dis}
dis所在集合中而不影响答案(如上图
(
2
,
3
)
(2,3)
(2,3)到
(
4
,
6
)
(4,6)
(4,6)),这样就消除了子树的影响。
推一下,答案加上
2
pre
(
2
r
−
1
−
r
)
2^{\text{pre}}(2^r-1-r)
2pre(2r−1−r)。其中
r
r
r表示距
x
x
x的距离为
dis
\text{dis}
dis的节点数,
pre
\text{pre}
pre就是小的
dis
\text{dis}
dis中的节点数。
上式中
2
r
−
1
2^r-1
2r−1表示任取距
x
x
x的距离为
dis
\text{dis}
dis的节点,但是一定最少取
2
2
2个,所以减去
r
r
r。
但是我们会发现答案还是不对……
因为有几种情况没考虑到。
如上图中
5
5
5点,它并不能做中点,可是统计时多加了,我们把它减去;
如果随意选择的话,
2
r
−
1
−
r
2^r-1-r
2r−1−r中存在没有选择最长的端点的情况,可以发现这些情况都是选择了次长的端点,于是我们把这些点产生的情况减去。
这样有点作为中点的情况考虑完了……
下面就应该是无中点的情况了。
接着要统计
pre
\text{pre}
pre,我们发现这种情况是不对称的,所以条件讨论瞬间就少了很多,因为边的中点作为中点,那么距这个点距离为
x
x
x的点和距这个点的儿子的距离为
x
x
x的点构成了答案,我们发现统计父亲时,儿子中的点可能被重复统计,所以我们要把它减去,然后这两个集合随便取即可,注意左右都要有点,因为取的是非空集合。
唉我去好崩溃啊……难怪就
6
6
6个A的……
写代码是更崩溃的……
那个BFS可能被卡常过不去,劼劼劼写了个DFS但是没看懂……
在学校题库卡常成功但是HDU上卡不过去,所以请自觉DFS……
可是DFS跑的好快啊!明明时间复杂度一样……
总时间复杂度
O
(
t
n
2
)
O(tn^2)
O(tn2),需要非常注意常数……(我输出优化都上了……)
UPD:能不能用树的点分治做?
树的点分治因为无法处理那个"如果选择了端点
(
7
,
9
)
(7,9)
(7,9),则
5
,
8
,
10
5,8,10
5,8,10也可以进入集合。"的情况也挂了……或许是我太弱没想到,欢迎dalao提出更优的解法QAQ
Code