LGP3349口胡

建议改为:如何使用FWT直接把反演题草过去

需要清楚 FWT 的本质是什么。

首先我们有一个明显的 DP:

\(dp[u][x][S]\) 代表 \(u\) 在图中为 \(x\),子树包含集合 \(S\) 的方案数。

那么我们只需要枚举可行的 \((v,y)\),然后做子集卷积就行。

复杂度 \(O(n^4 \times 2^n)\),无法通过。

考虑硬生生把子集卷积的 \(n^2 \times 2^n\) 优化成 \(n \times 2^n\)

现在我们将 \(dp[u][x]\) 看做一个整体,那么建出需要做子集卷积的转移树,若干个 \((u,x)\)\((v,y)\) 连接。

子集卷积是什么?将这些数丢到 \(n \times 2^n\) 的数组中去,然后跑 FWT,然后中间再对第一维度做一个卷积,最后 IFWT。

我们直接维护 FWT 的“点值”,只需要考虑如何解决掉多项式乘法。

因为只需要对 \((1,x)\)\(n\) 个数组进行 IFWT,所以这一部分复杂度即使暴力也是 \(O(n^3 \times 2^n)\) 的。

多项式乘法硬拆太难,考虑题意。

很明显只有第 \(siz[u]\) 个数组是有值的,因为别的很明显不合法。于是可以 \(O(2^n)\) 搞定这个过程。

然后对于某些集合不包含点的,完全可以还原数组后手动去掉。每个数组都还原一遍,复杂度为 \(O(n^2 \times n \times 2^n)\),完全可以通过此题。

实际上因为题目特性,直接做子集卷积都是对的(

posted @ 2022-02-06 16:26  Prean  阅读(42)  评论(0编辑  收藏  举报
var canShowAdsense=function(){return !!0};