tugetの妙妙屋

Loading...

集合幂级数学习笔记

先给个链接第一个让我理解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时为逆变换
posted @ 2025-10-31 10:02  tuget  阅读(6)  评论(0)    收藏  举报