FWT
$\mbox{FWT}$ 知识点总结
FWT及FMT
先来看看FMT
我们记得,$\mbox{FFT}$做的是这样的卷积:$\sum_{i+j=k}A_iB_j=C_k$
但如果我们把符号换一下呢?
比如说或/与卷积:$\sum_{i|j=k}A_iB_j=C_k,\sum_{i&j=k}A_iB_j=C_k$
还是像fft的思路,考虑一个数组,有个变换,使得数组变换后能实现对应位置相乘。
即:$FMT(A)[x]\cdot FMT(B)[x]=FMT(C)[x]$.
当是或卷积时,$FMT(A)[x]=\sum_{i|x}A_i$.
因为:$(\sum_{i|x}A_i)(\sum_{j|x}B_j)=\sum_{i|x,j|x}A_iB_j=\sum_{k|x}(\sum_{i|j=k}A_iB_j)=\sum_{k|x}C_k$
那如何快速求 $FMT(A)$ 及其逆变换呢?
与卷积与或卷积类似:$FMT(A)[x]=\sum_{x|i}A_i$
考虑基于枚举二进制位的分治,假设第 $i$ 位的二进制已经处理完了,然后看加上第 $i+1$ 位后答案应该是怎么样的:如果这一位是 0,那么不变,否则因为是枚举子集,加上 $i+1$ 位不取的结果即可。
那么逆变换就是把正变换的贡献减去即可。
1 | //或卷积模板,opt=1时为正变换,-1时为逆变换 |
或卷积的正变换其实就是高维前缀和(子集和),逆变换就是子集反演。
与卷积和或卷积类似了。
时间复杂度$O(n\log n)$
再来看看FWT
定义 $k$ 进制不进位加法:$a\bigoplus b=(a+b) % k$,减法类似。
FWT实际上就是求:$C_k=\sum_{i\bigoplus j=k}A_iB_j$
2进制FWT
此时不进位加法即为异或。以下 $n$ 满足 $n=2^x$
还是像fft的思路,考虑一个数组竖着排成一列变成一个 $n \times 1$ 的矩阵,然后有个变换,使得数组变换后能实现对应位置相乘。这个变换的实现就是令数组左乘一个 $n*n$ 的矩阵(可以回去看看fft的过程)。假设这个矩阵是 $T$,第 $i$ 行第 $j$ 列的数是 $T_{i,j}$
然后我们令$FWT(A)=TA$
因为要满足对应位置相乘,这里就是$FWT(A)[x]\cdot FWT(B)[x]=FWT(C)[x]$
由于$FWT(A)[x]=\sum_{i=0}^nT_{x,i}A_i$
代入上式得:$\sum_{i=0}^{n-1}T_{x,i}A_i\sum_{j=0}^{n-1}T_{x,j}B_j=\sum_{k=0}^{n-1}T_{x,k}C_k$
同时因为 $C_k=\sum_{i\bigoplus j=k}A_iB_j$
代入得:
$$\sum_{i=0}^{n-1}\sum_{j=0}^{n-1}T_{x,i}T_{x,j}A_iB_j=\sum_{k=0}^{n-1}\sum_{i\bigoplus j=k}T_{x,k}A_iB_j$$
因此满足 $T_{x,i}T_{x,j}=T_{x,i\bigoplus j}=T_{x,(i+j)\bmod 2}$ 即可。
因为 $T_{x,i}$ 满足上述性质,把 $i$ 写成二进制形式:$i=\overline{i_0i_1\dots i_m}(2)$
因此 $T_{x,i}$ 可以等于 $\Pi {j=0}^m T{x_j,i_j}$
同时还需要快速算出 $FWT(A)$:
不妨设 $i$ 在二进制中最高位为 $i_1$,舍去最高位后为 $i_0$.
考虑分治:
$$FWT(A)n[i]\=\sum{k=0}^{n-1}T_{i,k}A_k\=T_{i_1,0}\sum_{k=0}^{n/2-1}T_{i_0,k_0}A_{k}+T_{i_1,1}\sum_{k=n/2}^{n-1}T_{i_0,k_0}A_k\=T_{i_1,0}FWT(A_0){\frac{n}{2}}[i]+T{i_1,1}FWT(A_1)_{\frac{n}{2}}[i]$$
其中 $A_0$ 为 $A$ 的前 $n/2$ 位,$A_1$ 为后 $n/2$ 位。
因此只要能找到合适的 $T_{x,i}$,就能实现了。
只需考虑 $0\le x,i < 2$ 的情况即可。
满足:
$$T_{0,0}\times T_{0,0}=T_{0,0}\T_{0,0}\times T_{0,1}=T_{0,1}\T_{0,1}\times T_{0,1}=T_{0,0}\T_{1,0}\times T_{1,0}=T_{1,0}\T_{1,0}\times T_{1,1}=T_{1,1}\T_{1,1}\times T_{1,1}=T_{1,0}\$$
考虑写成矩阵形式,构造可得:
$$\begin{bmatrix} T_{0,0}&T_{0,1}\ T_{1,0}&T_{1,1}\end{bmatrix}=\begin{bmatrix}1&1\1&-1\end{bmatrix}=\begin{bmatrix}\frac{1}{2}&\frac{1}{2}\\frac{1}{2}&-\frac{1}{2}\end{bmatrix}^{-1}$$
带进程序里即可。
一个2进制FWT的模板:
1 | void FWT(ll *a,int n,int opt) |
2进制 $\mbox{FWT}$ 的正变换实际上就是 $FWT[i]=\sum_{j}A_j(-1)^{|i&j|}$.
k进制FWT
以下 $n$ 满足 $n=k^x$
前面同理,但还是要满足 $T_{x,i}T_{x,j}=T_{x,i\bigoplus j}=T_{x,(i+j)\bmod k}$,以及把 $i$ 写成 $k$ 进制形式:$i=\overline{i_0i_1\dots i_m}(k) $后,$T_{x,i}=\Pi {j=0}^m T{x_j,i_j}$
因此只需考虑 $T_{x,i}(0\le x,i < k)$ 即可。
想到1的 $k$ 次单位根:$T_{x,i}=\omega_{k}^{xi}$
那么:$\omega _{k}^i\omega _{k}^j=\omega_k^{(i+j)\bmod k}=\omega_k^{i\bigoplus j}$
由于矩阵需要存在逆矩阵,即要求满秩。
不妨想到范德蒙德矩阵:
$$\begin{bmatrix}
1 & 1 & 1 & \dots & 1\
1 & \omega _ k^1 & \omega _ k^2 & \dots &\omega _ k^{k-1} \
1 & \omega _ k^2 & \omega _ k^4 & \dots & \omega _ k^{2(k-1)}\
\vdots & \vdots & \vdots & \dots & \vdots\
1 & \omega _ k^{k-1} & \omega _ k^{2(k-1)} & \dots & \omega _ k^{(k-1)(k-1)}
\end{bmatrix}$$
逆矩阵和fft的一样。
这样子就能做任意进制的FWT了。
难度在求单位根上。
例题
1,UVA13277
模板题没啥好说的。
2,HDU6596
模板题 $\times 2$。
3,HDU6618
3进制FWT+倍增+状压,见此
4,Distance Between Sweethearts
5,CF1119H
思维难度较大,见此
6,牛客挑战赛36G
分治FWT,见此