[树] [HDU5830] Rikka with Subset II

题目传送门
还是翻译:
题目描述

我们都知道,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,vS 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) t1t100,表示测试数据组数,并有不超过 5 5 5组数据 n > 100 n>100 n>100
对于每组测试数据,第一行一个正整数 n ( 1 ≤ n ≤ 3000 ) n(1\le n\le 3000) n1n3000,接下来的 n − 1 n-1 n1行,每行两个数 u , v u,v uv,表示 u u u v v v之间有一条边。

输出 Output

对于每组测试数据,输出一行 n n n个数,第 i i i个数表示满足 value ( S ) = i − 1 \text{value}(S)=i-1 value(S)=i1的非空集合个数,这个答案可能很大,所以输出答案模 998244353 998244353 998244353.

我们知道,Rikka with Subset这道题是NTT,这道题应该不是。
(我就是闲的没事来看看……)
注意,选择 x x x个点,这 x x x个点未必连通。
好了怎么做?
暴力一点,枚举集合,一共 2 n − 1 2^n-1 2n1个,然后找到树上最长的路径,这样总复杂度是 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} 2k1种。
诶诶诶不对啊,我怎么少了这么多种?
不在路径上的点也可以进入集合并且不影响最长路径!
tree
如图所示的一棵树,如果选择了端点 ( 7 , 9 ) (7,9) (7,9),则 5 , 8 , 10 5,8,10 5810也可以进入集合。
这样枚举就不行了,我们还得沿着路径爬上去计算选择子树的情况……这样就是 O ( n 3 ) O(n^3) O(n3)的了。
我们换种方法,枚举中间点来消除子树对最长路径的影响。
诶中间点?如果中间是条边怎么办?
分情况讨论……
我们需要预处理出一个点向下 j ( 0 ≤ j ≤ n 2 ) j(0\le j\le \frac{n}{2}) j0j2n层的节点数,还要预处理出到一个点距离为 j ( 0 ≤ j ≤ n 2 ) j(0\le j\le \frac{n}{2}) j0j2n的节点数。第一个好办,一遍树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(2r1r)。其中 r r r表示距 x x x的距离为 dis \text{dis} dis的节点数, pre \text{pre} pre就是小的 dis \text{dis} dis中的节点数。
上式中 2 r − 1 2^r-1 2r1表示任取距 x x x的距离为 dis \text{dis} dis的节点,但是一定最少取 2 2 2个,所以减去 r r r
但是我们会发现答案还是不对……
因为有几种情况没考虑到。
如上图中 5 5 5点,它并不能做中点,可是统计时多加了,我们把它减去;
如果随意选择的话, 2 r − 1 − r 2^r-1-r 2r1r中存在没有选择最长的端点的情况,可以发现这些情况都是选择了次长的端点,于是我们把这些点产生的情况减去。
这样有点作为中点的情况考虑完了……
下面就应该是无中点的情况了。
接着要统计 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 5810也可以进入集合。"的情况也挂了……或许是我太弱没想到,欢迎dalao提出更优的解法QAQ
Code

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值