FWT学习笔记

FWT

FWT 即位运算卷积,用来快速计算形如 \(\sum\limits_{i\oplus j=k}f_ig_j\),其中 \(\oplus\) 表示某种位运算。

设 FWT(A) 是幂级数 A经过 \(\rm FWT\) 变换之后得到的幂级数。

我们需要令其满足 : \(A*B=C \Longleftrightarrow FWT(A)·FWT(B)=FWT(C)\)(点积)。

\(\rm FFT\) 是一个线性变换,我们也希望 \(\rm FWT\) 变换是线性的。

我们还不知道怎么变换,于是设 \(c(i,j)\) 为变换系数,即 \(A[j]\) 对 $FWT(A)[i] $ 的贡献系数。

\(FWT(A)[i]=\sum\limits_{j=0}^{n-1}c(i,j)A_j\)

\(FWT(A)*FWT(B)=FWT(C)\),得到:

\(FWT(A)[i]FWT(B)[i]=FWT(C)[i]\)

\(\sum\limits_{j=0}^{n-1}c(i,j)A[j]\sum\limits_{k=0}^{n-1}c(i,k)B[k]=\sum\limits_{p=0}^{n-1}c(i,p)C[p]\)

\(\sum\limits_{j=0}^{n-1}\sum\limits_{k=0}^{n-1}c(i,j)c(i,k)A[j]B[k]=\sum\limits_{p=0}^{n-1}c(i,p)C[p]\)

根据 \(A*B=C\) 得到:

\(C[p]=\sum\limits_{t1\oplus t2=p}A[t1]B[t2]\)

\(\sum\limits_{p=0}^{n-1}c(i,p)C[p]=\sum\limits_{p=0}^{n-1}c(i,p)\sum\limits_{t1\oplus t2=p}A[t1]B[t2]\)

\(\sum\limits_{j=0}^{n-1}\sum\limits_{k=0}^{n-1}c(i,j)c(i,k)A[j]B[k]=\sum\limits_{p=0}^{n-1}c(i,p)\sum\limits_{t1\oplus t2=p}A[t1]B[t2]\)

\(\sum\limits_{j=0}^{n-1}\sum\limits_{k=0}^{n-1}c(i,j)c(i,k)A[j]B[k]=\sum\limits_{p=0}^{n-1}\sum\limits_{t1\oplus t2=p}A[t1]B[t2]c(i,t1\oplus t2)=\sum\limits_{t1=0}^{n-1}\sum\limits_{t2=0}^{n-1}A[t1]B[t2]c(i,t1\oplus t2)\)

对比左右两边,我们发现只要满足 \(c(i,k)c(i,k)=c(i,j\oplus k)\) 就好了

现在,假设有了符合要求的 \(c\),如何优化FWT呢?

我们把 \(FWT(A)[i]=\sum\limits_{j=0}^{n-1}c(i,j)A[j]\) 按位折半,有
\(=\sum\limits_{j=0}^{\frac{n}{2}-1}c(i,j)A[j]+\sum\limits_{j=\frac{n}{2}}^{n-1}c(i,j)A[j]\)\(i'\)
\(i\) 去掉最高位的数字,那么有
\(\sum\limits_{j=0}^{\frac{n}{2}-1}c(i_0,j_0)c(i',j')A[j]+\sum\limits_{j=\frac{n}{2}}^{n-1}c(i_0,j_0)c(i',j')A[j]\)

\(=c(i_0,0)\sum\limits_{j=0}^{\frac{n}{2}-1}c(i',j')A[j]+c(i_0,1)\sum\limits_{j=\frac{n}{2}}^{n-1}c(i,j)A[j]\)

再设 \(A_0\) 下标首位为 \(0\) 的部分,如果 \(i_0=0\),则有:

\(FWT(A)[i]=c(0,0)FWT(A_0)[i]+c(0,1)FWT(A_1)[i]\;\;\;(i\in[0,\frac{n}{2}))\)

如果 \(i_0=1\),则有

\(FWT(A)[i+\frac{n}{2}]=c(1,0)FWT(A_0)[i]+c(1,1)FWT(A_1)[i]\;\;\;(i\in[0,\frac{n}{2}))\)

这就变成了一个规模为 \(\frac{n}{2}\) 的子问题。

因此关键就是 c 矩阵。

Or卷积

\(c=\begin{bmatrix}1&0\\1&1\end{bmatrix},c^{-1}=\begin{bmatrix}1&0\\-1&1\end{bmatrix}\)

即:

\[FWT(A)[i]=FWT(A_0)[i],FWT(A)[i+\frac{n}{2}]=FWT(A_0)[i]+FWT(A_1)[i] \]

\[IFWT(A)[i]=IFWT(A_0)[i],IFWT(A)[i+\frac{n}{2}]=IFWT(A_1)[i]-IFWT(A_0)[i] \]

And卷积

\(c=\begin{bmatrix}1&1\\0&1\end{bmatrix},c^{-1}=\begin{bmatrix}1&-1\\0&1\end{bmatrix}\)

即:
\(FWT(A)[i]=FWT(A_0)[i]+FWT(A_1)[i],FWT(A)[i+\frac{n}{2}]=FWT(A_1)[i]\)
\(IFWT(A)[i]=IFWT(A_0)[i]-IFWT(A_1)[i],IFWT(A)[i+\frac{n}{2}]=IFWT(A_1)[i]\)

Xor卷积

\(c=\begin{bmatrix}1&1\\1&-1\end{bmatrix},c^{-1}=\begin{bmatrix}0.5&0.5\\0.5&-0.5\end{bmatrix}\)

即:
\(FWT(A)[i]=FWT(A_0)[i]+FWT(A_1)[i],FWT(A)[i+\frac{n}{2}]=FWT(A_0)[i]-FWT(A_1)[i]\)
\(IFWT(A)[i]=0.5IFWT(A_0)[i]+0.5IFWT(A_1)[i],IFWT(A)[i+\frac{n}{2}]=0.5IFWT(A_0)[i]-0.5IFWT(A_0)[i]\)

CF850E Random Elections

题意:有3个候选人和 \(n\) 个投票的人,每个人对三个人的支持度排序,候选人之间两两比赛,每次比赛时,第 \(i\) 个人对哪个人更支持哪个就是1,否则是0,有函数 \(f\),会把这 \(n\) 个01变成0或1,1就是赢,否则是输,求有多少种方案使得有个人赢了两场。

思路:首先,哪个人赢了两场是不重要的,于是可以钦定 \(a\) 赢了两场,最后再乘3。a和 \(b,c\) 在第 \(i\) 个人处有 4 种情况,其中 \(b_i=c_i\) 的情况有两种,于是可以枚举 \(b_i!=c_i\) 求方案数,再乘上 \(2^{n-ppc(S)}\)。发现剩下的情况就是先令 \(g_k=\sum\limits_{i\oplus j=k}f_if_j\),然后有 \(ans=\sum\limits_{i=0}^{2^n}g_i2^{n-ppc(i)}\),可以直接用 FWT。复杂度 \(O(n2^n)\)

P3175 [HAOI2015] 按位或

题意:刚开始你有一个数字 \(0\),每一秒钟你会随机选择一个 \([0,2^n-1]\) 的数字,与你手上的数字进行或(C++,C 的 |,pascal 的 or)操作。选择数字 \(i\) 的概率是 \(p_i\)。保证 \(0\leq p_i \leq 1\)\(\sum p_i=1\) 。问期望多少秒后,你手上的数字变成 \(2^n-1\)

思路:首先用 \(\text{min-max}\) 容斥,设 \(Emax(S)\) 为遍历 \(S\) 中所有元素的最晚时间,那么 \(Emax(S)=\sum\limits_{T\subseteq S}(-1)^{|T|+1}Emin(T)\)

考虑怎么求 \(Emin(S)\)。根据期望的定义,有 \(Emin(S)=\sum\limits_{i=1}^{\infty}i[Pmin(S)=i]\),而 \(Pmin(S)=(\sum\limits_{T\cap S=\varnothing}P(T))^{i-1}(1-\sum\limits_{T\cap S=\varnothing}P(T))\),于是有 \(Emin(S)=\dfrac{1}{1-\sum\limits_{T\cap S=\varnothing}P(T)}=\dfrac{1}{1-\sum\limits_{T\subseteq\complement_US}P(T)}\)

现在的问题就是求子集和。可以直接用 FWT 解决。

Binary Table

题意:有一个 \(n\)\(m\) 列的表格,每个元素都是 \(0/1\) ,每次操作可以选择一行或一列,把 \(0/1\) 翻转,即把 \(0\) 换为 \(1\) ,把 \(1\) 换为 \(0\) 。请问经过若干次操作后,表格中最少有多少个 \(1\)

思路:考虑枚举翻转了哪些行,记 \(F(S)\) 表示 \(S\) 翻转后最少的 1 个数,那么 \(S\) 的答案就是 \(\sum F(S\oplus T_i)\)

考虑枚举 \(Y_i=S\oplus T_i\),那么就是 \(\sum\limits_{i}\sum\limits_{Y}[Y=T_i\oplus S]F(Y)\),记 \(cnt(Y)\) 表示有多少列是 \(Y\),那么就是 \(\sum\limits_{T}\sum\limits_{Y}[Y=S\oplus T]F(Y)cnt(T)=\sum\limits_{T}\sum\limits_{Y}[T\oplus Y=S]F(Y)cnt(T)\),发现这就是异或卷积,于是可以直接 FWT。

子集卷积

子集卷积是指对于给定序列 \(a,b\),求出 \(c_i=\sum\limits_{j|i=k,j\&k=0}a_j\times b_k\)

对于第一个限制可以直接 OR 卷积,但是现在有了第二个限制,就不那么好做了。

但是因为对于 \(i\&j=0\),有 \(popcount(i)+popcount(j)=popcount(i|j)\),于是我们可以记

\[f_{i,j}=\begin{cases}a_j&popcount(j)=i\\0&popcount(j)\ne i\end{cases},g_{i,j}=\begin{cases}b_j&popcount(j)=i\\0&popcount(j)\ne i\end{cases} \]

把 f 和 g 用 OR 卷积卷起来得到 h,然后 \(h_{popcount(i),i}\) 就是答案。

CF1034E Little C Loves 3 III

题意:有两个序列 \(a,b\),要求对每个 \(i\) 求出 \(\sum\limits_{j|k=i,j\&k=0}a_jb_k\),答案对 4 取模。

思路:容易想到子集卷积,复杂度是 \(O(n\log^2n)\)

考虑能否用上对 4 取模的条件。

\(ppc(x)=popcount(x)\),那么我们令 \(a_i\leftarrow a_i\times 4^{ppc(i)},b_i\leftarrow b_i\times 4^{ppc(i)}\),把 \(a,b\) 用 OR 卷积卷起来得到 \(c\),再令 \(c_i\leftarrow \dfrac{c_i}{4^{ppc(i)}}\) 就是答案。

为什么这样做是对的呢?假设 \(i\&j=0\),那么 \(\dfrac{4^{ppc(i)}\times 4^{ppc(j)}}{4^{ppc(i|j)}}=1\),而当 \(i\&j\ne 0\) 时,上式就是 4 的正整数次幂,再对 4 取模就没有贡献了,因此这样做是对的。

复杂度 \(O(n\log n)\)

posted @ 2024-02-13 09:57  Xttttr  阅读(14)  评论(0编辑  收藏  举报