其他分享
首页 > 其他分享> > 位运算卷积与快速沃尔什变换

位运算卷积与快速沃尔什变换

作者:互联网

我们要快速计算一类形如

\[c_i=\sum_{j\oplus k=i} a_jb_k \]

的问题,其中 \(\oplus\) 是 \(\operatorname{bitand},\operatorname{bitor},\operatorname{xor}\) 之一。

And 卷积 / Or 卷积

对于下标范围是 \([0,2^n-1]\) 的数列 \(a\),设

\[\mathrm{FMT}(a)_i=\sum_{j\operatorname{bitand} i=i} a_j. \]

我们设 And 卷积的运算符是 \(\times\),那么:

\[\begin{aligned} \mathrm{FMT}(a\times b)_i&=\sum_{j\operatorname{bitand} i=i} (a\times b)_j\\ &=\sum_{j\operatorname{bitand} i=i} \sum_{x\operatorname{bitand} y=j} a_xb_y\\ &=\sum_{x\operatorname{bitand} y\operatorname{bitand} i=i} a_xb_y\\ &=\mathrm{FMT}(a)_i\cdot \mathrm{FMT}(b)_i. \end{aligned} \]

因此,我们只需要对于 \(a\) 和 \(b\) 分别求出其 \(\mathrm{FMT}\),点积后再做 \(\mathrm{FMT}\) 的逆变换即可。

考虑这里的 \(\mathrm{FMT}\) 实际上就是高维前缀和,我们对于所有 \(i\in [0,n-1]\cap \Z\),在第 \(i\) 维做一遍前缀和即可。

Or 卷积是类似的。

void FMTAnd(ll (&arr)[Up],ll w){
	For(j,0,n-1) For(i,0,up) if(!((i>>j)&1)){
		arr[i]=(arr[i]+w*arr[i|(1<<j)])%Mod;
	}
}
void FMTOr(ll (&arr)[Up],ll w){
	For(j,0,n-1) For(i,0,up) if(!((i>>j)&1)){
		arr[i|(1<<j)]=(arr[i|(1<<j)]+w*arr[i])%Mod;
	}
}

快速沃尔什变换 FWT:Xor 卷积

这部分是抄的 command_block 博客。

Xor 没有 And 和 Or 那样优秀的性质。仍然考虑求出一个 \(\mathrm{FWT}(a)_i\),设它是

\[\mathrm{FWT}(a)_i=\sum_{j} C_{i,j}a_j. \]

我们需要让它满足:

\[\mathrm{FWT}(a)\cdot \mathrm{FWT}(b)=\mathrm{FWT}(a\times b). \]

其中 \(\times\) 表示 Xor 卷积。

我们大力展开上式:

\[\begin{aligned} \mathrm{FWT}(a)_i\cdot \mathrm{FWT}(b)_i&=\sum_j C_{i,j}a_j\sum_{k} C_{i,k}b_k.\\ \mathrm{FWT}(a\times b)_i&=\sum_j C_{i,j} (a\times b)_j\\ &=\sum_j C_{i,j} \sum_{x\operatorname{xor} y=j} a_xb_y\\ &=\sum_{j,k} a_jb_kC_{i,j\operatorname{xor} k}. \end{aligned} \]

对比左右两边的展开式,可以得到 \(C_{i,j}C_{i,k}=C_{i,j\operatorname{xor} k}\)。

我不理解啊??????然后为啥各位就互不影响了啊?????????????????????

标签:运算,卷积,sum,bitand,沃尔什,FWT,FMT,operatorname,mathrm
来源: https://www.cnblogs.com/alan-zhao-2007/p/bitwise-convolution-and-fwt.html