FWT
FWT是一种多项式转换算法,能解决下列问题:
[C_k=sum_{i|j=k} A_i imes B_j\
C_k=sum_{i&j=k} A_i imes B_j\
C_k=sum_{iigoplus j=k} A_i imes B_j
]
或卷积
也就是上面的第一条。
我们要求这样一个东西:
[FWT(A)[i]=sum_{j|i=i}A_j
]
求的方式如下:
[FWT(A)=
egin{cases}
(FWT(A_0),FWT(A_0+A_1)),n>0\
A,n=0
end{cases}
]
其中,((A))代表的是一个向量(多项式的向量表示),(n)是多项式的次数,(A_0)指的是(A)的前半部分(A的位数必须为2的整数次幂,如果多了就用0补齐),(A_1)同理。
然后(n=0)的时候很显然,(n>0)的话,大概就是:递归到第(x)层的时候,位置(i)存的是(i)在二进制意义下从高往低数(x)位的二进制子集(后面的位数相同)的所有数的和,递归到最后就是所有子集的和了。
接下来,对(FWT(A))和(FWT(B))按位相乘,就可以得到(FWT(C))了。
这里采用数学归纳法证明,位数为0的时候很显然,现在我们假设对于(A_0,A_1,B_0,B_1,C_0,C_1)上述结论都成立。
[egin{aligned}
FWT(A|B)&=FWT((A|B)_0,(A|B)_1)\
&=FWT(A_0|B_0,A_0|B_1+A_1|B_0+A_1|B_1)\
&=(FWT(A_0|B_0),FWT(A_0|B_0+A_0|B_1+A_1|B_0+A_1|B_1))\
&=(FWT(A_0) imes FWT(B_0),FWT(A_0) imes FWT(B_0)+FWT(A_1) imes FWT(B_0)+FWT(A_0) imes FWT(B_1)+FWT(A_1) imes FWT(B_1))\
&=(FWT(A_0) imes FWT(B_0),(FWT(A_0)+FWT(A_1)) imes (FWT(B_0)+FWT(B_1)))\
&=(FWT(A_0),FWT(A_0+A_1)) imes (FWT(B_0),FWT(B_0+B_1))\
&=FWT(A) imes FWT(B)
end{aligned}
]
于是证毕。
与卷积
形式如下:
[FWT(A)=
egin{cases}
(FWT(A_0+A_1),FWT(A_1)),n>0\
A,n=0
end{cases}
]
证明类似上面的或卷积。性质也是类似的。
异或卷积
形式如下:
[FWT(A)=
egin{cases}
(FWT(A_0+A_1),FWT(A_0-A_1)),n>0\
A,n=0
end{cases}
]
然而这个玩意似乎并没有什么性质。(我也不会证明 /doge)
IFWT
也就是上面几个的逆操作
或卷积:
[IFWT(A)=(IFWT(A_0),IFWT(A_1-A_0))
]
与卷积:
[IFWT(A)=(IFWT(A_0-A_1),IFWT(A_1))
]
异或卷积:
[IFWT(A)=(frac{IFWT(A_0+A_1)}{2},frac{IFWT(A_0-A_1)}{2})
]
代码实现
类似于FFT去做就好了。
特殊性质
不难发现,FWT出来的结果多项式的每一项的绝对值都不超过原来多项式每一项的和,所以搞FWT快速幂的时候可以利用这个性质来快速处理,不需要每一项都快速幂。
子集卷积
考虑我们要求下列的东西:
[C_k=sum_{i|j=k,i& j=0} A_i imes B_j\
]
记(cnt(x))为二进制下(x)的1的数量
这种情况下,我们按照每个二进制数的(cnt)分类讨论一下,也就是多加一维:(cnt)
最后(C_{cnt(k),k})就是我们要的答案。
例题
CF914G Sum the Fibonacci