FWT & FMT & 集合幂级数 题解集

CF449D Jzzhu and Numbers

简要题意

给定序列 \(\{a_n\}\),求有多少个子序列满足所有元素的按位与为 \(0\)

题解

F1

把二进制数 \(a_i\) 看作集合,即要求

\[\prod_i x^{a_i}+x^U \]

取 FMT,得

\[\begin{align*} \prod_i &\mathcal{F}(x^{a_i})+\mathcal{F}(x^U) \\=&\prod_i \ \end{align*} \]

F2

考虑一个背包 \(f_{i,j}\) 表示考虑 \(a_1\)\(a_i\),按位与结果为 \(j\) 的子序列数量。
有转移:

\[f_{i,j}=\sum_{k\&a_i=j}f_{i-1,k}+f_{i-1,j} \]

两端做 FWT:

\[\begin{align*} F_{i,j}&=\mathcal{F}(\sum_{k\&a_i=j}f_{i-1,k})+F_{i-1,j}\\ &=F_{i-1,j}G_{i-1,j}+F_{i-1,j}\\ &=F_{i-1,j}(G_{i-1,j}+1)\\ \end{align*} \]

其中 \(F_{i,\cdot}\)\(f_{i,\cdot}\) 的 FWT,\(G_{i,\cdot}\)\(g_{i,\cdot}\) 的 FWT,\(g_{i,j}=\begin{cases}1 & j=a_i\\0 & j\ne a_i\end{cases}\)

简单计算可以得到同 F1 的结果。

record

CF1119H Triple

简要题意

给定几个数:\(n,t,u,v,w\) 满足 值域 \(≤2^t\)。给出 \(n\) 个三元组 \((ai,bi,ci)\),表示有 \(x\)\(a_i\)​,\(y\)\(b_i\)​,\(z\)\(c_i\)​。对于每个 \(k\in[0,2t−1]\),请求出从每组选出一个数的异或和为 \(k\) 的方案数。

题解

我们要求

\[ans=\prod ux^{a_i}+vx^{b_i}+wx^{c_i} \]

其中 \(\prod\) 为异或卷积。考虑进行 FWT,有

\[\begin{align*} \mathcal{F}(ans)&=\mathcal{F}(\prod ux^{a_i}+vx^{b_i}+wx^{c_i})\\ &=\prod\mathcal{F}(ux^{a_i}+vx^{b_i}+wx^{c_i})\\ &=\prod u\mathcal{F}(x^{a_i})+v\mathcal{F}(x^{b_i})+w\mathcal{F}(x^{c_i}) \end{align*} \]

第二行之后及下文的 \(\prod\) 为点积。
注意到 \(\mathcal{F}(x^k)=\sum_S(\pm1)x^S\),因此

\[[x^k]\mathcal{F}(ans)=\prod(\pm u\pm v\pm w) \]

总共只有八种情况,对于每一个 \(k\),算出这八种情况在乘积中各出现多少次,然后快速幂就做完了。

考虑到八种情况还是太臃肿了,我们进行一个小 trick:将 \(b_i,c_i\) 异或上 \(a_i\),然后令 \(a_i=0\),最终输出答案的时候再异或回来即可,故 \(\mathcal{F}(x^{a_i})=\mathcal{F}(x^\varnothing)=\sum x^S\),所以 \(u\) 的系数恒为 \(1\),只剩下四种情况

\[u+v+w,u-v+w,u+v-w,u-v-w \]

记他们出现的次数分别为

\[c_1,c_2,c_3,c_4 \]

接下来考虑如何计算。直接算显然是不切实际的,但是我们考虑只计算 \(v\) 的系数的和 \(p_v\),则有对于最终答案的 \(x^k\) 这一项,

\[\begin{align*} p_v&=\sum[x^k]\mathcal{F}(x^{b_i})\\ &=[x^k]\sum\mathcal{F}(x^{b_i})\\ &=[x^k]\mathcal{F}(\sum x^{b_i}) \end{align*} \]

对于 \(w\)\(p_w\) 同理,再加上 \(c_1+c_2+c_3+c_4=n\),我们得到了三个线性无关的方程,考虑再找一个方程:
注意到 \(\mathcal{F}(x^{b_i})\mathcal{F}(x^{c_i})=\mathcal{F}(x^{b_i\oplus c_i})\)\(v,w\) 系数的乘积记为 \(p_{v\oplus w}\),有

\[\begin{align*} p_{v\oplus w}&=[x^k]\mathcal{F}(\sum x^{b_i\oplus c_i}) \end{align*} \]

至此四个方程集齐:

\[\begin{align*} &c_1+c_2+c_3+c_4=n\\ &c_1-c_2+c_3-c_4=p_v\\ &c_1+c_2-c_3-c_4=p_w\\ &c_1-c_2-c_3+c_4=p_{v\oplus w} \end{align*} \]

解出来之后做个快速幂,然后 IFWT 就做完了。

record

「THUSC2021」Emiya 家明天的饭

简要题意

给定 \(n\times m\) 权矩阵 \(w_{ij}\in\{-\infin\}\cup\mathbb{N}\),求从矩阵中取若干行和若干列,使得行列相交处的和最大。
\(n\le 20,m\le 10^6\)

题解

注意到 \(n\) 很小,我们可以枚举选取的行的集合。
考虑记 \(L_i\) 为第 \(i\) 行中不为 \(-\infin\) 的列的集合,记 \(f(S)\) 为选的行的集合为 \(S\) 时的最大收获,则有

\[f(S)=\sum_{i\in S}\sum_{j\in L_S}w_{ij}\\ L_S=\bigcap_{i\in S}L_i \]

进一步转化:

\[\begin{align*} f(S)=&\sum_{i\in S}\sum_{j}[j\in L_S]w_{ij}\\ =&\sum_j\sum_{i\in S}[j\in L_S]w_{ij}\\ =&\sum_j f_j(S) \end{align*} \]

其中

\[\begin{align*} f_j(S)=&\begin{cases} \sum_{i\in S} w_{ij} & (j\in L_S)\\ 0 & (j\notin L_S) \end{cases} \end{align*} \]

注意到 \(f_j(S)\) 只在 \(L_S\) 的子集内有值,所以我们尝试通过子集加/高维前缀加来生成 \(f_j(S)\)
很容易发现,如果我们对 \(L_S\) 的所有子集加上 \(\sum_{i\in L_S}w_{ij}\);对于 \(x\in L_S\),让 \(L_S\setminus x\) 的所有子集减去 \(w_{xj}\) 即可生成 \(f_j(S)\)

对于每一个 \(j\) 我们单点加,然后一起做一次 FMT 后缀和即可。复杂度 \(O(n2^n+nm)\)

tips:遇到奇奇怪怪的集合式子如果不能直接写成卷积的形式,可以考虑化成一系列序列相加,然后尝试让每个序列都能由简单序列的 FWT/FMT 生成。
这时候就不要考虑用形式化的式子去做差分前缀和看能不能变简单了,直接考虑能不能通过少量的前缀和/后缀和/前后缀差分等操作产生序列即可。

record

posted @ 2023-04-04 19:18  Watware  阅读(47)  评论(0编辑  收藏  举报