集合幂级数

写在前面

  • 大概就是看了一些题解总结了一下得出的东西

  • 肯定有很多错误,欢迎指出

  • 目前学习的不多,希望轻喷

问题引入

UOJ #310. 【UNR #2】黎明前的巧克力

  • 对于一个大小为 \(n\) 的异或为 \(0\) 的集合,有 \(2^n\) 种选择的方案使得选出两个集合的异或和为 \(0\)

  • 对于每个元素的贡献都是 \(2\) ,那么其实我们就要求 FWT 意义下的 \([x^0]\prod (1+2x^{a_i})\)

  • 一个想法就是对于每个元素都正变换,然后点值乘起来,然后再逆变换,但是复杂度太高了

  • 考虑 FWT 正变换的意义是 \((-1)^{c(i\&j)}\) ,那么就可以发现正变换后每个数只会是 \(-1\)\(3\)

  • 那么我们考虑求出每一位有多少位是 \(-1\) ,多少位是 \(3\)

  • 我们可以考虑将每一位加起来然后用一元一次方程来解出每一位 \(-1\) 的个数,剩下的个数就是 \(3\)

  • \(FWT(A)+FWT(B)=FWT(A+B)\) ,所以我们将 \(FWT(\sum 1+2x^{a_i})\) 正变换后,求出每一位 \(-1\)\(3\) 的个数,然后算出乘积,最后逆变换回来,但是就是 \([x^0]IFWT\)

进阶问题

CF1119H Triple

  • 显然答案就是 \(\prod(Xx^{a_i}+Yx^{b_i}+Zx^{c_i})\) FWT 变换后的每一项的系数

  • 还是考虑按照上面的做法,但是这样每一位的数字就会有 8 种可能性,太麻烦了

  • 考虑利用异或的自反性,我们将每一组的每个数字都异或上 \(a_i\) ,最终的结果异或上 $\bigoplus_{i=1}^n a_i $ 就是原答案了

  • 那么现在的三元组就是 \((0,b_i\bigoplus a_i,c_i\bigoplus a_i)\) ,下面的 \(b,c\) 以新的三元组为标准

  • 那么实际上就是求 \(\prod (X+Yx^{b_i}+Zx^{c_i})\)

  • 那么现在的可能就只有 4 种了,考虑仍然像上面那样用方程来解

  • \(X-Y-Z=d_1,X-Y+Z=d_2,X+Y-Z=d_3,X+Y+Z=d_4\)

  • 注意到我接下来所谈到的 \(d\) 都是关于 FWT 数组的某一项的相关数量

  • 第一个方程: \(d_1+d_2+d_3+d_4=n\)

  • 其实可以发现这里的 \(d_1,d_2,d_3,d_4\)\(X,Y,Z\) 是没有关系的,只和 \(a_i,b_i,c_i\) 有关系

  • 我们让 \(X,Y,Z\) 取特殊值来设出接下来的 3 个方程

  • \(X=0,Z=0,Y=1\) 的时候,每一项的贡献只和 \(Y\) 有关

  • 第二个方程: \(d_3+d_4-d_1-d_2=[x^i]FWT\)

  • \(X=0,Y=0,Z=1\) 的时候,每一项的贡献只和 \(Z\) 有关

  • 第三个方程: \(d_2+d_4-d_1-d_3=[x^i]FWT\)

  • 最后一个方程,我们考虑 \(Y,Z\) 同时做贡献,也就是令 \(x^{b_i\bigoplus c_i}\) 的系数为 1 ,其余的为 0

  • 对于每一位的系数实际上就是 \(\sum_i (-1)^{j\&(b_i\bigoplus c_i)}=\sum_i (-1)^{j\& b_i}(-1)^{j\&c_i}\)

  • 第四个方程: \(d_1-d_2-d_3+d_4=[x^i]FWT\)

  • 然后就解这四个方程就可以知道对于每一位所有值分别的个数了,然后还原成原本的值,再 IFWT 回去就得到了答案数组,输出答案的时候记得 \(\bigoplus_{i=1}^n a_i\)

问题模型

  • 然而通过特殊的处理处理了上面的类似问题还不够,考虑这个问题的模型

求形如 $\prod_{i=1}^n \sum_{j=0}^{len-1} w_jx^{a_{i,j}} $ FWT 变换后的每一项的系数,假设 \(a_{i,j}\leq 2^{k}\)

  • 最暴力的肯定就是 \(O(n2^kk)\) ,瓶颈在于 \(O(n2^k)\),考虑能不能像上面一样解方程

想法一

  • 一共有 \(2^{len}\) 种取值,假设出现次数为 \(v_0,v_1,...,v_{2^{len}-1}\) ,对于一位如果为 \(1\) ,说明此处的实际取值为 \(-1\)

  • 我们此时理论上需要 \(2^{len}\) 个方程,第一种就是和为 \(n\) ,所以还需要 \(2^{len}-1\)

  • 仍然考虑取特殊值

  • 我们考虑枚举每一个子集的贡献,去掉一个都不选的情况,刚好就会有 \(2^{len}-1\) 个方程出现

  • 设取的子集的二进制表示为 \(T\),假设为集合 \(S\) ,那么对于每一项的系数就是 \(\sum_i (-1)^{j\&{a_{i,S_1}}}(-1)^{j\&{a_{i,S_2}}}...(-1)^{j\& a_{i,S_n}}\)

  • 那么考虑当前方程的每一个 \(v_i\) 的系数就是 \((-1)^{T\&i}\)

  • 方程设好后直接暴力解

  • 那么理论复杂度就是 \(O(2^{len}2^kk+2^k2^{3len}+2^kk)\)

  • 复杂度的瓶颈在于解方程的 \(O(n^3)\)

想法二

  • 当我们枚举一个子集 \(T\) ,特殊值取 \(1\) 的时候,在方程种 \(v_i\) 的系数就是 \((-1)^{T\& i}\)

  • 实际上这是 FWT 系数,现在我们考虑将每一位单独看,下面所讨论都是针对于每一位

  • 我们考虑将数组 \(v\) FWT 后,每一项 \(T\) 就是 \(\sum_{i} (-1)^{i\& T} v_i\) ,可以发现这个东西就是关于集合 T 的方程,假设这个数组为 \(H\) ,那么我们只要将 \(H\) 逆变换回去就是 \(v\) 数组了

  • 对于一个子集关于一项方程的答案是很好求的,我们记录下每个子集关于每一项的答案

  • 然后对于每一项逆变换回去就可以得到这一项的 \(v\)

  • 理论复杂度就是 \(O(2^{len}2^kk+2^k2^{len}len+2^kk)\)

  • 这里就不再是暴力的解方程,而是利用了一个很巧妙的性质

posted @ 2022-07-23 15:14  Kzos_017  阅读(58)  评论(0编辑  收藏  举报