Preface

我们知道,对于下面的式子
快速沃尔什变换(FWT)_多项式

快速沃尔什变换(FWT)_多项式_02为+运算时,可以用FFT优化
快速沃尔什变换(FWT)_多项式_02为位运算(or,and,xor)时是否也有一种优化呢

答案是肯定的。

FWT

首先,对于多项式,我们定义快速沃尔什变换(FWT)_卷积_04为某一种位运算卷积
显然它满足交换律、结合律

类似FFT。我们利用分治的思想,将多项式快速沃尔什变换(FWT)_FWT_05分成两部分快速沃尔什变换(FWT)_多项式_06快速沃尔什变换(FWT)_卷积_07,表示其下标二进制最高位为0的部分(前快速沃尔什变换(FWT)_FWT_08项)和最高位为1的部分(后快速沃尔什变换(FWT)_FWT_08项),不足的不妨用0补齐

那么A是由快速沃尔什变换(FWT)_多项式_10两部分拼接而成,记为快速沃尔什变换(FWT)_卷积_11
对于一个多项式A,我们尝试找到一种变换快速沃尔什变换(FWT)_FWT_12
满足:
快速沃尔什变换(FWT)_位运算_13
并且它存在逆变换,满足
快速沃尔什变换(FWT)_多项式_14

这样对于两个多项式位运算卷积我们就可以先将它们变换,直接按项相乘,再变换回来

下面结论就来了

or卷积

快速沃尔什变换(FWT)_多项式_02为or运算时
快速沃尔什变换(FWT)_卷积_16
快速沃尔什变换(FWT)_多项式_17

当然只有一个数时就是它本身
实际上,快速沃尔什变换(FWT)_卷积_18

and卷积

快速沃尔什变换(FWT)_多项式_02为and运算时
快速沃尔什变换(FWT)_FWT_20
快速沃尔什变换(FWT)_位运算_21

xor 卷积

快速沃尔什变换(FWT)_多项式_02为xor运算时
快速沃尔什变换(FWT)_多项式_23
快速沃尔什变换(FWT)_卷积_24

并且对于所有的变换,都满足快速沃尔什变换(FWT)_位运算_25

证明可以用数学归纳法,拆成两部分推导一波…
博主太懒不想推了

接下来就可以快乐写FWT了
过程和FFT是类似的,不过不需要蝴蝶变换的反位

Code

or

void FWT(int *a,bool pd)
{
for(int m=2,half=1;m<=M;half=m,m<<=1)
for(int j=0;j<M;j+=m)
fo(i,0,half-1)
{
a[i+j+half]+=a[i+j]*((pd?)-1:1);
}
}

And

void FWT(int *a,bool pd)
{
for(int m=2,half=1;m<=M;half=m,m<<=1)
for(int j=0;j<M;j+=m)
fo(i,0,half-1)
{
a[i+j]+=a[i+j+half]*((pd?)-1:1);
}
}

Xor

void FWT(int *a,bool pd)
{
for(int m=2,half=1;m<=M;half=m,m<<=1)
for(int j=0;j<M;j+=m)
fo(i,0,half-1)
{
int v=a[i+j+half];
a[i+j+half]=a[i+j]-v,a[i+j]+=v;
if(pd) a[i+j]/=2,a[i+j+half]/=2;
}
}

一个应用(子集卷积)

有时候我们常常要碰到这样的问题
快速沃尔什变换(FWT)_卷积_26
也就是子集卷补集

这似乎不太好处理
巧妙的转化一下
快速沃尔什变换(FWT)_卷积_27,其中快速沃尔什变换(FWT)_多项式_28为i在二进制下1的个数

如果我们将所有数按bit分组,每一组存一个多项式,只有bit数对应的项才有值,其他项为0

这就变成快速沃尔什变换(FWT)_卷积_29
相当于里面的位运算卷积外面套一个普通的卷积。

枚举快速沃尔什变换(FWT)_多项式_30,再枚举i,快速沃尔什变换(FWT)_FWT_31快速沃尔什变换(FWT)_位运算_32可以提前预处理好,这里直接相乘
又由于快速沃尔什变换(FWT)_位运算_25
因此我们可以直接累加进快速沃尔什变换(FWT)_卷积_34,最后全部做完了再一次性快速沃尔什变换(FWT)_卷积_35回来

注意不同的bit[n]之间的F是不能加在一起的,一个bit[n]做完以后只有bit对应的项的值是有意义的。

这样预处理和后面乘积累加时间复杂度都是快速沃尔什变换(FWT)_位运算_36,空间复杂度快速沃尔什变换(FWT)_多项式_37