快速沃尔什变换

FWT 用于解决对下标进行位运算的卷积问题。

及求 \(\displaystyle c_i=\sum_{j\oplus k=i}a_jb_k\),其中 \(\oplus\) 是二元位运算的一种。

板子

P4717 【模板】快速莫比乌斯/沃尔什变换 (FMT/FWT)

\(\oplus=\operatorname{or},\operatorname{and},\operatorname{xor}\) 分别求出 \(c\).

记对序列 \(a\) 进行 FWT 后的序列为 \(fwt[a]\).

我们希望能够做到 \(a\rightarrow fwt[a]\)\(b\rightarrow fwt[b]\)\(fwt[c]\rightarrow c\) 的时间都是 \(O(n\log n)\)\(fwt[c]=fwt[a]\cdot fwt[b]\) 这部分的时间是 \(O(n)\) 的。

此时 \(\displaystyle c_i=\sum_{j|k=i}a_jb_k\).

\(j|i=i,k|i=i\rightarrow (j|k)|i=i\).

构造 \(\displaystyle fwt[a]_i=\sum_{j|i=i}a_j\).

那么

\[fwt[a]\times fwt[b]=\sum_{j|i=i}\sum_{k|i=i}a_jb_k \]

\[=\sum_{(j|k)|i=i}a_ib_k=fwt[c] \]

FWT

现在思考 \(a\rightarrow fwt[a]\) 的过程。

\[fwt[a]_i=\sum_{j|i=i}a_j \]

把当前区间分为两部分,记为 \(A_0\)\(A_1\),它们在最高二进制位的值分别为 \(0,1\).

发现 \(A_0\) 的子集即其本身,\(A_1\) 的子集是它本身与最高位为 \(0\) 的子集,也就是

\[fwt[a]=\operatorname{merge}(fwt[A_0],fwt[A_0]+fwt[A_1]) \]

\(\operatorname{merge}\) 表示拼接,\(+\) 表示对应二进制位相加。

这样时间复杂度为 \(O(n\log n)\).

IFWT

怎么反演使得 \(fwt[a]\rightarrow a\)

已知 \(A_0=fwt[A_0]\)\(A_1=fwt[A_0]+fwt[A_1]\),容易得到

\[ifwt[a']=\operatorname{merge}(ifwt[A_0'],ifwt[A_1']-ifwt[A_0']) \]

  • code

\(x=1/-1\) 代入即可,中间做一遍点积。

void OR(int *a,int x){
	for(int p=2,k=1;p<=n;p<<=1,k<<=1)
		for(int i=0;i<n;i+=p)
			for(int j=0;j<k;j++)
				a[i+j+k]+=a[i+j]*x;
}

与或运算十分相似,构造 \(\displaystyle fwt[a]_i=\sum_{j\And i=i}a_i\).

  • FWT/IFWT

\[fwt[a]=\operatorname{merge}(fwt[A_0]+fwt[A_1],fwt[A_1]) \]

\[ifwt[a']=\operatorname{merge}(ifwt[A_0']-ifwt[A_1'],fwt[A_1']) \]

  • code
void AND(int *a,int x){
	for(int p=2,k=1;p<=n;p<<=1,k<<=1)
		for(int i=0;i<n;i+=p)
			for(int j=0;j<k;j++)
				a[i+j]+=a[i+j+k]*x;
}
异或
  • 构造

定义 \(x\oplus y=\operatorname{popcount}(x\And y)\operatorname{mod}2\).

\((i\oplus j)\operatorname{xor}(i\oplus k)=i\oplus(j\operatorname{xor}k)\).

构造 \(\displaystyle fwt[a]_i=\sum_{i\oplus j=0}a_j-\sum_{i\oplus j=1}a_j\).

那么

\[fwt[a]\times fwt[b] \]

\[=\Bigg(\sum_{i\oplus j=0}a_j\sum_{i\oplus k=0}b_k\Bigg)-\Bigg(\sum_{i\oplus j=0}a_j\sum_{i\oplus k=1}b_k\Bigg)-\Bigg(\sum_{i\oplus j=1}a_j\sum_{i\oplus k=0}b_k\Bigg)+\Bigg(\sum_{i\oplus j=1}a_j\sum_{i\oplus k=1}b_k\Bigg) \]

\[=\sum_{i\oplus(j\operatorname{xor}k)=0}a_jb_k-\sum_{i\oplus(j\operatorname{xor}k)=1}a_jb_k \]

\[=fwt[c] \]

  • FWT/IFWT

\(A_0\) 中的数高位为 \(0\),在 \(\oplus\) 运算中对答案的贡献不变。

\(A_1\) 中的数高位为 \(1\),由于 \(1\And0=0\),运算结果为负。

那么

\[fwt[a]=\operatorname{merge}(fwt[A_0]+fwt[A_1],fwt[A_0]-fwt[A_1]) \]

同理有

\[ifwt[a']=\operatorname{merge}(\frac{ifwt[A_0']+ifwt[A_1']}{2},\frac{ifwt[A_0']-ifwt[A_1']}{2}) \]

  • code

IFWT 时 \(x\) 的值为 \(1/2\).

void XOR(int *a,int x){
	for(int p=2,k=1;p<=n;p<<=1,k<<=1)
		for(int i=0;i<n;i+=p)
			for(int j=0;j<k;j++){
				a[i+j]+=a[i+j+k];
				a[i+j+k]=a[i+j]-a[i+j+k]*2;
				a[i+j]*=x,a[i+j+k]*=x;
			}
}

record


P6097 【模板】子集卷积

\[h_i=\sum_{j|k=i,j\And k=0}f_jg_k \]

\(n\le 20\).

\(O(3^n)\) 的暴力做法不是很理想。

\(\displaystyle f(i,S)=\sum_{T\in S,|T|=i}f(T)\),有 \(f(|S|,S)=f(S)\).

有一个性质是

\[h(i,S)=\sum_{j=0}^{i}f(j,S)g(i-j,S) \]

也就是说应有 \(|j|+|k|=|i|\).

把所有的 \(f(i,S)\)\(g(i,S)\) FWT 出来,再对 \(h(i,S)\) 做 IFWT 即可。

容易看出来应使用 FWTOR。

record


一些题目

Binary Table

可以将 \(01\) 矩阵的任意行和列取反,最小化 \(1\) 的个数。

\(n\le 20\)\(m\le 10^5\).


\(n\) 的值入手。

一个想法是考虑翻转了那些行,记为 \(s\),然后对每一行的 \(now\) 比较
\(|now|\)\(|now\operatorname{xor}s|\),时间复杂度 \(O(2^nm)\).

\(g_x\)\(x\)\(0,1\) 的出现次数更小的那个,\(f_x\)\(x\) 的出现次数。

若已知 \(s\) 容易枚举答案即

\[\sum_{i=0}^{2^n-1}f_i\cdot g_{i\operatorname{xor}s} \]

\[\sum_{i=0}^{2^n-1}f_i\times\sum_{k=0}^{2^n-1}g_k[i\operatorname{xor}s=k] \]

也就是

\[\sum_{i=0}^{2^n-1}f_i\times\sum_{k=0}^{2^n-1}g_k[i\operatorname{xor}k=s] \]

直接上 FWT 即可。

record


Sum the Fibonacci

定义五元组 \((a,b,c,d,e)\) 合法当且仅当:

  • \(a,b,c,d,e\in[1,n]\)

  • \((s_a|s_b)\And s_c\And (s_d\operatorname{xor}s_e)=2^i(i\in Z)\)

  • \(s_a\And s_b=0\)

对于所有合法的五元组,求

\[\sum f(s_a|s_b)\cdot f(s_c)\cdot f(s_d\operatorname{xor}s_e) \]

其中 \(f\) 是斐波那契数列,答案对 \(\rm 1e9+7\) 取模。

\(n\le 10^6\)\(0\le s_i<2^{17}\).


记这三个不同的东西为 \(i,j,k\).

\[\sum_{p}\sum_{i\And j\And k=2^p}f_i\cdot f_j\cdot f_k\cdot(\sum_{s_a|s_b=i,s_a\And s_b=0}1)\cdot(\sum_{s_c=j}1)\cdot(\sum_{s_d\operatorname{xor}s_e=k}1) \]

记三个括号里的东西为 \(A_i\)\(B_j\)\(C_k\).

\(A_i\) 用子集卷积做,时间复杂度 \(O(n\log^2 n)\).

\(C_k\) 用 FWTXOR 做,时间复杂度 \(O(n\log n)\).

最后三个函数用 FWTAND 卷起来。

record


Xor Spanning Tree

一棵带边权的仙人掌,环总数 \(\le42\),问其最小异或生成树及方案数。


一个环应删一条边,令 \(f_{k,i}\) 表示第 \(k\) 个环边权为 \(i\) 的边数。

另外地,记所有边地异或和为 \(sum\),那么 \(f_{0,sum}=1\).

将所有的 \(f_k\) FWTXOR 即可。

可悲的是这题要用双模数。

record


*P4221 [WC2018] 州区划分

\(n\) 个点划分为 \(k\) 个连通块(只保留连接同块内的点的边),满足每个连通块中不存在欧拉回路。

记划分后 \(k\) 个块的点集为 \(V_1,V_2,\dots,V_k\)\(\operatorname{Sum}(i)=\sum_{j\in V_i}w_j\),求

\[\sum_{\{V\}}\prod_{i=1}^{k}\Big(\frac{\operatorname{Sum}(i)}{\sum_{j=1}^{i}\operatorname{Sum}(j)}\Big)^p \]

答案对 \(998244353\) 取模。


划分 \(\{V_k\}\)\(\{C_s\}\) 不同当且仅当 \(k\not=s\)\(\exists i\in[1,k],V_i\not=C_i\).

\(0\le n\le 21\)\(0\le m\le\frac{n(n-1)}{2}\)\(0\le p\le 2\)\(1\le w_i\le 100\).

子图有欧拉回路即图连通且有奇点。容易用 \(O(m2^n)=O(n^22^n)\) 的时间判定。

\(f_S\) 为划分集合 \(S\) 的答案,那么

\[f_S=\sum_{i|j=S,i\And j=0}f_i\times\operatorname{calc}(S,j) \]

其中 \(\displaystyle\operatorname{calc}(S,j)=(\frac{\operatorname{Sum}(j)}{\operatorname{Sum}(S)})^p=\frac{\operatorname{Sum}(j)^p}{\operatorname{Sum}(S)^p}\).

那么

\[f_S=\operatorname{Sum}(S)^{-p}\times \sum_{i|j=S,i\And j=0}f_i\operatorname{Sum}(j)^p \]

考虑怎么处理这个转移系数。

\(|S|\) 从小到大转移,算出所有 \(f_S(|S|=i)\) 后变换回去再乘上转移系数。

时间复杂度 \(O(n^22^n)\)\(\rm TL=10s\sim 15s\),可以接受。

record


[ABC212H] Nim Counting

给定 \(n,k\) 和数组 \(\{A_k\}\),进行如下操作:

  • 选择一个 \(m\in[1,n]\).

  • 生成 \(\{B_m\}\) 满足 \(\forall i\in[1,m],B_i\in A\).

  • 两人在序列 \(\{B_m\}\) 上玩 Nim 游戏。

问所有 \(\sum_{i=1}^{n}k^i\) 种游戏中先手必胜的方案数。答案对 \(998244353\) 取模。

\(n\le 2\times 10^5\)\(1\le A_i,k<2^{16}\)\(A_i\) 互不相同。


不难发现要用多项式。

定义乘法 \(x^a\times x^b=x^{a\operatorname{xor}b}\).

\(\displaystyle f(x)=\sum_{i=1}^{k}x^{A_i}\),即求

\[\sum_{w>0}[x^w]\sum_{i=1}^{n}f(x)^i \]

暴力 FWT 时间 \(O(nk\log k)\).

注意到 FWT 具有线性性,算出 \(fwt[f]\) 后令每一项的 \(x\leftarrow \sum_{i=1}^{n}x^i\) 后 IFWT 即可。

时间复杂度 \(O(k\log k+k\log n)\).

record


*[ABC220H] Security Camera

给一张无向图,给一些点安摄像头(可以一个也不安),问有偶数条边被监控到的方案数。

一条边被监控到当且仅当它的两个端点有至少一个被安装了摄像头。

保证无自环、重边。

\(2\le n\le 40\)\(1\le m\le \frac{n(n-1)}{2}\).


考虑把 “至少有一个端点被选” 这个条件转化。

\(m\) 为图的边数,\(n\) 为一个导出子图 \(G\) 的边数,\(p\) 为非 \(G\) 中的点的导出子图 \(G'\) 的边数,且 \(z=m-n-p\).

那么 \(n\) 表示是两个点都选的边数,\(p\) 表示两个点都不选的边数,那么 \(z\) 就是刚好选一个的边数。

根据题意应有 \(z+n\equiv0(\operatorname{mod}2)\),那么有 \(m\equiv p(\operatorname{mod}2)\).

\(n\)\(p\) 是相对的,也就是说我们现在把条件转化为了:

  • 两个端点都被选,且边数奇偶性与 \(m\) 相同。

考虑折半,将 \([0,n-1]\) 这些点按编号分为两部分。

\(f_S\) 为只考虑左点,点集 \(S\) 的导出子图边数奇偶性,\(g_T\) 为只考虑右点,点集 \(T\) 的导出子图边数奇偶性,\(a_S\) 为右点中与左点点集 \(S\) 连边数量是奇数的点集。

即求

\[\sum_{S,T}[f_S\oplus g_T\oplus(|a_S\cap T|\operatorname{mod}2)=m\operatorname{mod}2] \]

\(|a_S\cap T|\operatorname{mod}2\) 表示 \(S,T\) 之间边数的奇偶性。

枚举 \(f_S=x,g_T=y\),变成

\[\sum_{S,T}[f_S=x][g_T=y][|a_S\cap T|\operatorname{mod}2=(m\operatorname{mod}2)\oplus x\oplus y] \]

考虑计算

\[h_z=\sum_{S,T}[a_S\cap T=z][f_S=x][g_T=y] \]

\[b_z=\sum_{S}[a_S=z][f_S=x] \]

\[c_T=[g_T=y] \]

\[h_z=\sum_{S\cap T=z}b_Sc_T \]

FWTAND 即可。时间复杂度 \(O((n+m)2^\frac{n}{2})\).

最大点照着题解卡到了 1920ms.但是为什么那一篇可以只跑 1.2s.

record


P5387 [Cnoi2019] 人形演舞

两人在一个可重正整数集合 \(V\) 上博弈,\(V\) 中元素值域为 \([1,m]\).

每次一个人选取 \(x\in V\)\(y\in[1,x]\),满足 \(x\oplus y\in[0,x)\),令 \(x\leftarrow x\oplus y\).

无法操作视失败。问多少种 \(V\) 可使先手获胜。答案模 \(998244353\).

\(|V|\le 10^{18}\)\(m\le 10^6\).


这种情况只能考虑 SG 函数了。

  • \(x=0\)

此时 \(SG(x)\) 只能为 \(0\).

  • \(x=2^k\)

\(x\) 只能变为 \(x'=0\),故 \(SG(x)=1\).

  • \(x=2^k+n(0<n<2^k)\)

假设 \(SG(x)=n+1\),考虑数学归纳法。

假设 \(SG(x=2^k+n)=n+1\) 对于 \(x'<x\) 均成立,考虑选择 \(y\).

\(y\) 最高位为 \(0\),那么 \(x\oplus y\in[2^k,2^k+n)\),其间出现了 \([1,n]\),且 \(0\) 也是后继状态,故 \(SG(2^k+n)(0<n<2^k)=n+1\).

综上可以用 \(O(m)\) 的时间求出 \(SG(1\sim m)\).

现在要选出 \(|V|\) 个数使它们的 SG 值的异或和不为 \(0\),FWTXOR 之后令 \(x\leftarrow x^{|V|}\) 即可。

时间复杂度 \(O(m\log m+m\log |P|)\),用欧拉降幂优化。

record


[ABC288G] 3^N Minesweeper

给出 \(n\),有数列 \(b_0,\dots,b_{3^n-1}\),值均为 \(0\)\(1\)

对于数 \(x\),对所有满足如下条件的 \(y\),将 \(b_y\) 相加得到 \(a_x\)

  • 在三进制下 \(x\)\(y\) 的每一位的差的绝对值 \(\le 1\)

给出 \(\{a\}\),还原 \(\{b\}\)


考虑 \(b\Longrightarrow a\) 的贡献系数,写为矩阵:

\[c=\begin{bmatrix}1&1&0\\1&1&1\\0&1&1\end{bmatrix} \]

\(b=a\times c^{-1}\),可以得到

\[c^{-1}=\begin{bmatrix}0&1&-1\\1&-1&1\\-1&1&0\end{bmatrix} \]

实现过程类似三进制下的 FWT。

record


[ARC137D] Prefix XORs

给定 \(\{a_n\}\)\(m\),对 \(k\in[1,m]\) 求如下操作 \(k\) 次后 \(\{a_n\}\) 的值:

  • 对每个 \(i\in[1,n]\),同时令 \(a_i=a_1\oplus a_2\oplus \dots\oplus a_i\)

\(1\le n,m\le 10^6\)\(0\le a_i<2^{30}\)


对于单个 \(k\),即求

\[\sum_{i=0}^{n-1}\binom{k-1+i}{i}a_{n-i} \]

运算均为异或。

考虑 \(\binom{k-1+i}{i}\bmod 2\) 何时为 \(1\)。由 Lucas 定理,二进制下 \(i\)\(k-1+i\) 的子集。

\((k-1+i)\operatorname{and}i=i\Longrightarrow k-1\in\complement_{U}i\)

我们做一遍 FWT 即可。

record


P3175 [HAOI2015] 按位或

初始 \(x=0\),不断随机 \(y\in[0,2^n-1]\),令 \(x\leftarrow x\operatorname{or} y\),其中选到 \(i\) 的概率为 \(p_i\)\(\sum p_i=1\)

\(x=2^n-1\) 的期望步数。

\(n\le 20\),精度要求 \(10^{-6}\)


Min-Max 容斥,观察

\[E(\max(S))=\sum_{T\subseteq S}(-1)^{|T|+1}E(\min(T)) \]

\(E(\max(S))\) 视为集合 \(S\) 二进制下 \(1\) 的最晚期望出现时间,\(E(\min(S))\) 视为 \(1\) 的最早期望出现时间。

怎么求 \(E(\min(S))\),其实满足选到了和 \(S\) 有交的数即可,那么

\[E(\min(S))=\frac{1}{\sum_{T\cap S \ne\varnothing}P(T)} \]

把这个变成无交,枚举补集 \(S'\) 的子集:

\[E(\min(S))=\frac{1}{1-\sum_{T\subseteq S'}P(T)} \]

求出和式,FWTOR 即可。

record


*Little C Loves 3 III

给定值域为 \([0,3]\) 的长为 \(2^n\) 的数列 \(\{a\}\)\(\{b\}\),下标从 \(0\) 开始,求它们子集卷积后的结果 \(\{c\}\),答案模 \(4\)

\(n\le 21\),TL=1s,ML=62.5MB。


考虑一种精妙的构造,使得我们在一遍 FWTOR 的过程中将 \(i\operatorname{and}j\ne 0\)\((i,j)\) 的贡献消去。

\(f(x)=\operatorname{popcount}(x)\)

\(i\operatorname{and}j=0\)\(\dfrac{4^{f(i)}\cdot 4^{f(j)}}{4^{f(i\operatorname{or}j)}}=1\)

\(i\operatorname{and}j\ne 0\),此时 \(|i|+|j|>|i\operatorname{or}j|\),有 \(\dfrac{4^{f(i)}\cdot 4^{f(j)}}{4^{f(i\operatorname{or}j)}}\bmod 4=0\)

于是令 \(a_x\leftarrow a_x\cdot 4^{f(x)}\)\(b_x\leftarrow b_x\cdot 4^{f(x)}\),FWTOR 得到 \(\{c\}\)\(x\) 处的答案即为 \(\dfrac{c_x}{4^{f(x)}}\bmod 4\)

字符数组要加 \(1\) 才行?不是很理解。

record

posted @ 2023-08-21 16:41  SError  阅读(27)  评论(0编辑  收藏  举报