前言
定义如下记号:
一个集合幂级数 \(F(x)=\sum_{S}a_Sx^S\)。其中 \(S\) 是全集 \(U\) 的一个子集。
\(n=|U|\)。
在集合幂级数上的一个二元运算 \(\times\),相当于多项式的乘法,\(x^S\times x^T=x^{S\times T}\)。\(\times\) 可以是或卷积、异或卷积、子集卷积。下文中讨论的多为子集卷积,其他情况会给出明确说明。
集合幂级数的卷积
要讨论卷积,我们就要先定义 \(\times\)。
一般地,我们考虑类似 FFT 的思路,设计一个变换,使得两个集合幂级数的卷积等于正变换后的点值对应点积再做逆变换。这样就能在 \(O(n2^n)\) 的复杂度内完成卷积。
即,\(A(x)B(x)=IFWT(FWT(A)FWT(B))\)。乘法为点积。
\(FWT\) 还具有线性性,即 \(FWT(A+B)=FWT(A)+FWT(B)\)。
或卷积
\(\times\) 为或卷积运算。
构造 \(F(x)=\sum_{S}a_Sx^S\) 的正变换:\(\sum_Sx^S\sum_{T\subseteq S}a_T\)。逆变换:\(\sum_Sx^S\sum_{T\subseteq S}(-1)^{[S\ne T]}a^T\)。
即,\(FWT(F)=\sum_Sx^S\sum_{T\subseteq S}a_T\),\(IFWT(F)=\sum_Sx^S\sum_{T\subseteq S}(-1)^{[S\ne T]}a^T\)。
异或卷积
\(\times\) 为异或卷积运算。
构造正变换:\(\sum_S x^S\sum_{T} (-1)^{|S\cap T|}a_T\),逆变换:\(\sum_S x^S\sum_{T}(-\frac12)^{|S\cap T|}a_T\)。
证明考虑:
\[\sum_S x^S\left(\sum_{T_1} (-1)^{|S\cap T_1|}a_{T_1}\right)\left(\sum_{T_2} (-1)^{|S\cap T_2|}b_{T_2}\right)=\sum_S x^S\left(\sum_{T_1,T_2}(-1)^{|S\cap T_1|+|S\cap T_2|}a_{T_1}b_{T_2}\right)=\sum_S x^S\left(\sum_{T_1,T_2}(-1)^{|S\cap(T_1\oplus T_2)|}a_{T_1}b_{T_2}\right)\]
其中 \(\oplus\) 为集合的对称差运算。
扩展
可以看出,各种变换的本质是一个下标为集合的系数矩阵 \(A_{U\times U}\),表示从 \(\sum_S a_Sx^S\) 变换得到 \(\sum_S x^S\sum_T A_{T,S}a_T\)。正变换的矩f阵和逆变换的矩阵应该互为逆矩阵。由此也可知,做正逆变换的先后顺序可以互换。
(这里提一点,一般来说矩阵需要规定行列都是一个 \([1,n]\) 内的整数,但是在仅讨论矩阵乘法时,我们无需关注行列的顺序,因此下标可以为集合。)
子集卷积
定义 \(\times\) 为子集卷积。
求解子集卷积的复杂度为 \(O(n^22^n)\)。
下文中的 \(\times\) 均为子集卷积。
逆
已知 \(F(x),F(x)*G(x)=1\),求 \(G(x)\)。
注意需要保证 \(F(x)\) 的常数项不为 \(0\),否则 \(F^{-1}(x)\) 不存在。
一样的。
求出 \(F(x)\) 的点值之和,再去解出 \(G(x)\) 的点值即可。
\(e^{F(x)}\)
需要保证常数项为 \(0\),不然常数项不收敛。
\(e^{F(x)}=1+F(x)+F^2(x)/2!+F^3(x)/3!+...+F^n(x)/n!\)。
朴素的求法是 \(O(n^32^n)\)。进一步可以做到 \(O(n^22^n)\)。
具体地,根据组合意义:
把所有子集按最高位分成 \(n\) 组,依次加入。加入一组就是一次子集卷积。复杂度 \(O(\sum_{i=0}^n i^22^i)=O(n^22^n)\)。
\(\ln F(x)\)
需要保证常数项为 \(1\)。
上面求 \(e^{F(x)}\) 的逆过程。代码整个倒过来,子集卷积变成子集卷积逆。
也许没有成形的组合意义?
给定一张无向图,对每个生成子图求选择边的子集使得连通的方案数。
设这个方案数为 \(G(x)\),\(2^{E}\) 为 \(F(x)\)。
则有 \(e^{G(x)}=F(x)\),于是 \(G(x)=\ln F(x)\)。
\(\sum a_kF^k(x)\)
也被称作“集合幂级数复合多项式”。
还是类似的分组。再多一个维度,设 \(F_{i,j}(x)\) 表示到了 \(2^i\) 还差 \(j\) 次卷积。
注意到 \(j\) 的范围只有 \([0,n-1-i]\)。化简复杂度:
\(T(n)=O(\sum_{i=0}^{n-1}i^2(n-i)2^i)\)。
考虑 \(T(n)-T(n-1)=O(\sum_{i=0}^{n-1} i^22^i+n^22^n)=O(n^22^n)\)。
再求和,\(T(n)=O(n^22^n)\)。
出现了很神奇的事情:上面的算法复杂度实际上是 \(O(n^22^n)\) 的。
黎明前的巧克力
我们考虑这件事情等价于选出一个集合 \(S\),使得 \(S\) 中的异或和为 \(0\),并得到 \(2^{|S|}\) 的贡献。
即异或卷积意义下的 \([x^0]\prod (1+2x^{a_i})\)。
变乘法为 FWT,考虑 \(FWT(\prod (1+2x^{a_i}))=\prod FWT(1+2x^{a_i})\)。考虑 FWT 后得到的多项式系数只有 \(3,-1\) 两种。假设点乘后 \(i\) 次项的系数为 \(3^x(-1)^y\),则 \(x+y=n\),\(3x-y=\sum FWT(1+2x^{a_i})_i\)。现在我们如果能求出 \(FWT\) 的和,就可以解出 \(x,y\) 的值,进而解出 \(FWT\) 的点积,也就得到了整个多项式,再做 IFWT 即可。
FWT 具有线性性,FWT 的和等于和的 FWT 即可,求出和再 FWT 即可。
总结一下,我们依次做了以下步骤:
- 把若干的小多项式加和;
- 对和做 FWT;
- 根据和的 FWT 解出积的 FWT;
- 对结果做 IFWT,完毕。
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |