「总结」多项式生成函数相关(2)

这次主要来说一下\(FWT\)
我们知道\(FFT\)是一种变换。
我们要构造的\(FWT\)也是一种变换。

\(FWT\)是用来干什么的呢?
用来求位运算卷积。
或许这么说还是不够明确。
我们定义卷积是这样一个东西:

\[c_k=\sum\limits_{i\circ j}a_ib_j \]

里面那个圈表示一种运算。
普通卷积就是\(+\)
狄利克雷卷积就是\(*\)
子集卷积就是\(\subseteq\)
那么位运算卷积呢?
\(and,or,xor\)

其实\(and\)\(or\)还是比较简单的,而\(xor\)是最难的。

1.\(or\)卷积
我们要求这种形式的卷积:

\[c_k=\sum\limits_{i\ or\ j=k}a_ib_j \]

我们设我们的变换为\(T(A)\),逆变换为\(IT(A)\)
这个变换按照\(FFT\)的套路来说的话,需要满足:
T(AB)=T(A)T(B)
A
B=IT(T(A)T(B))
也就是卷积变成对位乘法。

如果这样构造的话(其实我也不知道怎么想到这么造的):

\[T(A)_j=\sum\limits_{i\ or\ j=j}A_i \]

那么我们展开一下上面的卷积:

\[T(A*B)_i=\sum\limits_{j\ or\ i=i}\sum\limits_{k\ or\ l=j}A_kB_l=\sum\limits_{k\ or\ l\subseteq i}A_kB_l \]

\[(T(A)T(B))_i=\sum\limits_{k\ or\ i=i}A_K\sum\limits_{l\ or\ i=i}B_l=\sum\limits_{k\ or\ l\subseteq i}A_kB_l \]

所以说是对的。
下面说怎么计算\(or\)卷积。
我们考虑这个东西的转移是怎么样的。
首先假设\(A\)的两半\(A_0\)\(A_1\)的变换已经计算出来了,我们现在来求\(A\)的变换。
我们设\(merge(A,B)\)为连接两个数组的函数。
那么:

\[T(A)=merge(T(A_0),T(A_0)+T(A_1)) \]

为什么呢?
因为当前这一位最高位为0的情况属于为1的情况的子集,所以把\(A_0\)加到\(A_1\)那边去就可以了。
逆变换就显然了。

\[IT(A)=merge(IT(A_0),IT(A_1)-IT(A_0)) \]

减回去就完了。

2.\(and\)卷积
我们要求这种形式的卷积。

\[c_k=\sum\limits_{i\ and\ j=k}a_ib_j \]

同样构造变换\(T\)
考虑这样的变换:

\[T(A)_i=\sum\limits_{i\ and\ j=i}a_j \]

展开一下:

\[T(A*B)_i=\sum\limits_{i\ and\ j=i}\sum\limits_{k\ and\ l=j}A_kB_l=\sum\limits_{i\subseteq k\ and\ l}A_kB_l \]

\[(T(A)T(B))_i=\sum\limits_{k\ and\ i=i}\sum\limits_{l\ and\ i=i}A_kB_l=\sum\limits_{i\subseteq k\ and\ l}A_kB_l \]

得到了点值对乘的式子了。
类似或卷积。

\[T(A)=merge(T(A_0)+T(A_1),T(A_1)) \]

\[IT(A)=merge(IT(A_0)-IT(A_1),IT(A_1)) \]

3.\(xor\)卷积
这里复读一下\(rvalue\)学长(姐)的讲解。(其实是我想不出其他的证明方法)

对于一个二进制数\(x\),我们设\(d(x)\)为其二进制\(1\)个数的奇偶性。
那么有如下结论:

\[d(i\ and\ k)\ xor\ d(j\ and\ k)=d((i\ xor\ j)\ and\ k) \]

首先\(and\ k\)相当于没有,这就是改变二进制位数的区别。
剩下的很显然。
\(i\)每次多出来一个\(1\),总体的\(1\)的奇偶性就会变化。

尝试构造如下变换:

\[T(A)_i=\sum\limits_{d(i\ and\ j)=0}A_j-\sum\limits_{d(i\ and\ j)=1}A_j \]

展开一下:

\[T(A*B)_i=\left(\sum\limits_{d(i\ and\ j)=0}\sum\limits_{k\ xor\ l=j}A_kB_l\right)-\left(\sum\limits_{d(i\ and\ j)=1}\sum\limits_{k\ xor\ l=j}A_kB_l\right) \]

\[\begin{aligned}\\ (T(A)T(B))_i&=\left(\sum\limits_{d(i\ and\ j)=0}A_j-\sum\limits_{d(i\ and\ j)=1}A_j\right)\left(\sum\limits_{d(i\ and\ j)=0}B_j-\sum\limits_{d(i\ and\ j)=1}B_j\right)\\ &=\left(\sum\limits_{d(a\ and\ i)\ xor\ d(b\ and\ i)=0}A_aB_b\right)-\left(\sum\limits_{d(a\ and\ i)\ xor\ d(b\ and\ i)=1}A_aB_b\right)\\ &=\left(\sum\limits_{d((a\ xor\ b)\ and\ i)=0}A_aB_b\right)-\left(\sum\limits_{d((a\ xor\ b)\ and\ i)=1}A_aB_b\right)\\ &=\left(\sum\limits_{d(i\ and\ j)=0}\sum\limits_{k\ xor\ l=j}A_kB_l\right)-\left(\sum\limits_{d(i\ and\ j)=1}\sum\limits_{k\ xor\ l=j}A_kB_l\right)\\ \end{aligned}\]

卷积性变换构造的是对的了。
考虑该怎么计算。

\[T(A)=merge(T(A_0)+T(A_1),T(A_0)-T(A_1)) \]

如果最高位为0的话,那么无论如何这个\(and\)运算都是0,不会改变贡献。
直接在左边即可。
如果最高位为1的话,对于右侧的值会产生多一个1的贡献,这样会导致奇偶性取反,所以取反加上去。
逆变换的话:

\[IT(A)=merge(\frac{IT(A_0)+IT(A_1)}{2},\frac{IT(A_0)-IT(A_1)}{2}) \]

这样的话就可以快速求位运算卷积了

现在来说一下咕了的\(FMT\)
好。
其实我们现在要求得的\(FMT\)和或运算卷积是一样的。
他需要求得就是:

\[f(S)=\sum\limits_{T|R=S}g(T)h(R) \]

这个东西该怎么求呢?
我们做一个和或运算卷积一样的东西即可了。

\[F(S)=\sum\limits_{T\subseteq S}f(T) \]

这样和或运算的证明方式一样,这一定是对的\(DFT\)
直接对位相乘即可。
那他既然可以被或运算代替为什么还存在呢?
(常数小码量小)
分别考虑每一位的贡献就可以了。

具体来说。
我们枚举二进制位的每一位,来判断这个元素的归属。
选或者没有选。
那么也就是:

\[F_i[j]=F_{i-1}[j]+F_{i-1}[j-(1<<i)] \]

这样转移就可以了。
我们发现可以把第一维滚掉。
这样代码就非常好写了。
这样我们就会求\(FMT\)了。
\(Upd:\)以上全是放屁。
下面严谨证明:
\(G_i=\{1,2,...,i\}\)
设:

\[\hat{F(S)}^{(i)}=\sum\limits_{T\subseteq S}[(S-T)\subseteq G_i]f(T) \]

初始化:$$\hat{F(S)}^{(0)}=F(S)$$
转移:
1.\(i\notin S\),那么\(\hat{F(S)}^{(i)}=\hat{F(S)}^{(i-1)}\),因为之前的均不含\(\{i\}\)
2.\(i\in S\),那么\(\hat{F(S)}^{(i)}=\hat{F(S)}^{(i-1)}+\hat{F(S-i)}^{(i-1)}\),前者\(T\)中一定不含有\(\{i\}\),而后者\(T\)中一定含有\(\{i\}\)
这样迭代\(n\)次就可以了。
最终求得的\(\hat{F}=FMT(F)\)

那么怎么求\(IFMT\)呢?

我们知道:

\[F(S)=\sum\limits_{T\subseteq S}f(T) \]

子集反演得:

\[f(S)=\sum\limits_{T\subseteq S}(-1)^{|S|-|T|}F(T) \]

这样直接就把加号写成减号就可以了。因为多一个元素那么答案整体上会乘一个-1。

下面的才是重点。
\(FMT\)求子集卷积(其实也可以\(FWT\)
也就是这样的式子:

\[f(S)=\sum\limits_{T\subseteq S}h(T)g(S-T) \]

要求更加严格了,不可以有交集。
那么:

\[f(S)=\sum\limits_{T\subseteq S,R\subseteq S}[|T|+|R|=|S|][T|R=S]h(T)g(R) \]

这样就简单了。
我们按照集合大小将这个东西分成\(n\)种。
也就是:

\[F_i(S)=\sum\limits_{T\subseteq S}[|T|=i]f(T) \]

这样还是可以用:
\(H_{i}(T)\)\(G_{n-i}(R)\)来做或卷积了。
这样复杂度变成了:
\(O(n^22^n)\)

posted @ 2019-12-12 11:53  Lrefrain  阅读(405)  评论(0编辑  收藏  举报