大概题意是: 给你一颗无根树,每一个结点有点权, 有多少颗子树的结点乘积不超过m?子树的定义是树上的连通块。
首先我们考虑另一个问题,假设给你一颗有根树,所以包含根的子树有多少种满足乘积不超过m?
考虑树形dp的做法,定义dp[i][j]是在i被选取后 这颗子树中乘积为j的子树方案数,这样每次将两颗子树合并的复杂度是m*m的。但实际上子树大小限制了状态数不会那么多,所以每次计算一个点的贡献的复杂度是 o(m)的。
这里题解有一个很巧妙的求法,因为如果一个点被选取,那么他的父亲一定被选取。如果一个点不被选取,那么它子树中的所有点也不会被选取。所以当我们从fa->u时,dp[fa]已经包含了u不被选取的情况(因为u还没有被搜索,没有任何节点统计了贡献)。那么我们只需要统计u被选取的情况,因为u被选取了,那么fa一定也被选取了,所以u可以继承fa的信息,然后继续递归即可。
但是这样dfs一次的复杂度是n*m的,还是有点吃不消。注意题目中要求的是乘积。我们可以考虑剩余的子树大小,比如当前有两颗乘积为m,m-1的子树,那么他们都只能在添加大小为1的子树,所以状态可以合并。其实就是一个整除分块。所以dp[i][j]表示i点在选取后还能添加大小为j的子树的方案数,这样状态数只有。复杂度是o(n*