FWT 笔记
给定长度为 \(2^n\) 两个序列 \(A,B\),设
分别当 \(\textup{op}\) 是 or, and, xor 时求出 \(C\)。
FWT 就是解决所谓位运算卷积问题的。
我们用 \(C=A\cdot B\) 表示 \(C_k=A_kB_k\)。
构造一个 \(\textup{FWT}(A),\textup{FWT}(B)\),使得 \(\textup{FWT}(C)=\textup{FWT}(A)\cdot\textup{FWT}(B)\),从而 \(C=\textup{FMT}^{-1}(\textup{FMT}(A)\cdot\textup{FWT}(B))\)。
我们考虑构造形如 \(\textup{FWT}(A)_i=\sum_{j}w(i,j)A_j\) 的东西。
那么就有
于是
好的,凭借某些惊人的直觉,便可以猜出其分别为
不难验证其正确性。
如何求?
这很类似于 FFT,所以我们考虑分治求解
现在,从低到高枚举每一位,每一段内的 FWT 已经被求解,假设现在是 \(k\)。
OR
我们考虑每一个形如 \(i2^k+2^{k-1}+j\) 的位置,就有
可能不是很好理解,所以我们来看代码:
template<typename T>
void FWTor(int n,T *f){
n=(1<<n);
for(int o=2,k=1;o<=n;o<<=1,k<<=1)
for(int i=0;i<n;i+=o)
for(int j=0;j<k;++j)
f[i+j+k]=f[i+j+k]+f[i+j];
}
仔细观察就会发现这本质和高维前缀和是一致的。
AND
我们考虑每一个形如 \(i2^k+j\) 的位置,就有
template<typename T>
void FWTand(int n,T *f){
n=(1<<n);
for(int o=2,k=1;o<=n;o<<=1,k<<=1)
for(int i=0;i<n;i+=o)
for(int j=0;j<k;++j)
f[i+j]=f[i+j+k]+f[i+j];
}
仔细观察就会发现这本质和高维后缀和是一致的。
XOR
我们考虑每一个形如 \(i2^k+j\) 和 \(i2^k+2^{k-1}+j\) 的位置,就有(为了区分,我们用 \(A^{\prime}\) 表示之后的数组)
template<typename T>
void FWTxor(int n,T *f){
n=(1<<n);
T tmp;
for(int o=2,k=1;o<=n;o<<=1,k<<=1)
for(int i=0;i<n;i+=o)
for(int j=0;j<k;++j){
tmp=f[i+j];
f[i+j]=f[i+j+k]+f[i+j];
f[i+j+k]=tmp-f[i+j+k];
}
}
考虑怎么反过来?
这里我们直接解方程组,就可以有
某些理解中把这视为矩阵求逆,其实就是这意思。
IOR
我们考虑每一个形如 \(i2^k+2^{k-1}+j\) 的位置,就有
可以和之前代码合并
template<typename T>
void FWTor(int n,T *f,int type){
n=(1<<n);
for(int o=2,k=1;o<=n;o<<=1,k<<=1)
for(int i=0;i<n;i+=o)
for(int j=0;j<k;++j)
f[i+j+k]=f[i+j+k]+type*f[i+j];
}
仔细观察就会发现这本质和高维差分是一致的。
IAND
我们考虑每一个形如 \(i2^k+2^{k-1}+j\) 的位置,就有
可以和之前代码合并
template<typename T>
void FWTand(int n,T *f,int type){
n=(1<<n);
for(int o=2,k=1;o<=n;o<<=1,k<<=1)
for(int i=0;i<n;i+=o)
for(int j=0;j<k;++j)
f[i+j]=f[i+j]+type*f[i+j+k];
}
仔细观察就会发现这本质和高维差分是一致的。
IXOR
我们考虑每一个形如 \(i2^k+j\) 和 \(i2^k+2^{k-1}+j\) 的位置,就有(为了区分,我们用 \(A^{\prime}\) 表示之后的数组)
template<typename T>
void FWTxor(int n,T *f,int type){
n=(1<<n);
T tmp;
for(int o=2,k=1;o<=n;o<<=1,k<<=1)
for(int i=0;i<n;i+=o)
for(int j=0;j<k;++j){
tmp=f[i+j];
f[i+j]=f[i+j+k]+f[i+j];
f[i+j+k]=tmp-f[i+j+k];
f[i+j]=f[i+j]*type,f[i+j+k]=f[i+j+k]*type;
}
}
全部使用 CV 大法完成。
恭喜你已经会了 FWT!

浙公网安备 33010602011771号