集合幂级数学习笔记
先给个链接第一个让我理解FWT的文章。
FWT基本思想是通过构造一种线性变换,即令 \(F\) 为集合幂级数,那么 \(F_S\) 为 \(F\) 中的 \(S\) 那一项,那么 \(FWT(F)_S=\sum_{T} c(S,T)F_T\)。
而要实现对于 \(C= A \times B\) 有 \(FWT(C)_S=FWT(A)_S \times FWT(B)_S\),展开即
\[\sum_{T}\limits c(S,T)C_T=\sum\limits_{i=0}^{n-1} c(S,i)A_i \sum\limits_{j=0}^{n-1} c(S,j)B_j
\]
而 \(C_S=\sum\limits_{X\bigoplus Y=S}A_X B_Y\),所以有
\[\sum\limits_{T} c(S,T) \sum\limits_{X^Y=S} A_X B_Y=\sum\limits_{i=0}^{n-1} c(S,i)A_i \sum\limits_{j=0}^{n-1} c(S,j)B_j
\]
也就是
\[\sum\limits_{i=0}^{n-1}\sum\limits_{j=0}^{n-1} c(S,i \bigoplus j) A_i B_j=\sum\limits_{i=0}^{n-1}\sum\limits_{j=0}^{n-1} c(S,i)c(S,j) A_i B_j
\]
所以只需要满足 \(c(S,i\bigoplus j)=c(S,i)c(S,j)\) 即可。注意到 \(i\bigoplus j\) 是位运算,所以设 \(x\) 二进制下第 \(k\) 为 \(x_k\),那么
\[c(S,i \bigoplus j)=\prod\limits_{k=0} c(S,i_k j_k)=\prod\limits_{x=0} c(S,i_x) c(S,j_x)
\]
所以只需要确定 \(c(\{0,1\},\{0,1\})\) 的值就能构造出这个变换。
通过分讨得出,满足要求的矩阵有两种:
\[\begin{aligned}
\begin{bmatrix}
1&1\\-1&1
\end{bmatrix}
\end{aligned}
\]
\[\begin{aligned}
\begin{bmatrix}
1&1\\1&-1
\end{bmatrix}
\end{aligned}
\]
注意到后面这种等价于 \((-1)^{(i \& j)}\),具有简单表述形式,所以一般使用第二种。
具体实现上,考虑按最高位分类,对于前一半的位置,最高位为 \(0\),所以对应的系数都为 \(1\),\(FWT(A)_i=FWT(A_0)_i+FWT(A_1)_i\),相应的后一半的位置最高位为 \(1\),\(FWT(A)_{i+\frac{n}{2}}=FWT(A_0)-FWT(A_1)\),逆变换对矩阵求个逆即可。
code
void fwt(ll *a,int fl)
{
int i,j,k;
for(i=1;i<(1<<n);i<<=1)for(j=0;j<(1<<n);j+=(i<<1))
for(k=0;k<i;++k){
ll x=a[j+k],y=a[i+j+k];
a[j+k]=(x+y)%mod,a[j+k+i]=(x-y+mod)%mod;
if(fl)a[j+k]=a[j+k]*inv%mod,a[j+k+i]=a[j+k+i]*inv%mod;
}
}//fl为1时为逆变换

浙公网安备 33010602011771号