快速沃尔什变换
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\rightarrow fwt[a]\) 的过程。
把当前区间分为两部分,记为 \(A_0\) 和 \(A_1\),它们在最高二进制位的值分别为 \(0,1\).
发现 \(A_0\) 的子集即其本身,\(A_1\) 的子集是它本身与最高位为 \(0\) 的子集,也就是
\(\operatorname{merge}\) 表示拼接,\(+\) 表示对应二进制位相加。
这样时间复杂度为 \(O(n\log n)\).
IFWT
怎么反演使得 \(fwt[a]\rightarrow a\)?
已知 \(A_0=fwt[A_0]\),\(A_1=fwt[A_0]+fwt[A_1]\),容易得到
- 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
- 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/IFWT
\(A_0\) 中的数高位为 \(0\),在 \(\oplus\) 运算中对答案的贡献不变。
\(A_1\) 中的数高位为 \(1\),由于 \(1\And0=0\),运算结果为负。
那么
同理有
- 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;
}
}
P6097 【模板】子集卷积
求
\(n\le 20\).
\(O(3^n)\) 的暴力做法不是很理想。
设 \(\displaystyle f(i,S)=\sum_{T\in S,|T|=i}f(T)\),有 \(f(|S|,S)=f(S)\).
有一个性质是
也就是说应有 \(|j|+|k|=|i|\).
把所有的 \(f(i,S)\),\(g(i,S)\) FWT 出来,再对 \(h(i,S)\) 做 IFWT 即可。
容易看出来应使用 FWTOR。
一些题目
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\) 容易枚举答案即
也就是
直接上 FWT 即可。
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\)
对于所有合法的五元组,求
其中 \(f\) 是斐波那契数列,答案对 \(\rm 1e9+7\) 取模。
\(n\le 10^6\),\(0\le s_i<2^{17}\).
记这三个不同的东西为 \(i,j,k\).
记三个括号里的东西为 \(A_i\),\(B_j\),\(C_k\).
\(A_i\) 用子集卷积做,时间复杂度 \(O(n\log^2 n)\).
\(C_k\) 用 FWTXOR 做,时间复杂度 \(O(n\log n)\).
最后三个函数用 FWTAND 卷起来。
Xor Spanning Tree
一棵带边权的仙人掌,环总数 \(\le42\),问其最小异或生成树及方案数。
一个环应删一条边,令 \(f_{k,i}\) 表示第 \(k\) 个环边权为 \(i\) 的边数。
另外地,记所有边地异或和为 \(sum\),那么 \(f_{0,sum}=1\).
将所有的 \(f_k\) FWTXOR 即可。
可悲的是这题要用双模数。
*P4221 [WC2018] 州区划分
将 \(n\) 个点划分为 \(k\) 个连通块(只保留连接同块内的点的边),满足每个连通块中不存在欧拉回路。
记划分后 \(k\) 个块的点集为 \(V_1,V_2,\dots,V_k\),\(\operatorname{Sum}(i)=\sum_{j\in V_i}w_j\),求
答案对 \(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\) 的答案,那么
其中 \(\displaystyle\operatorname{calc}(S,j)=(\frac{\operatorname{Sum}(j)}{\operatorname{Sum}(S)})^p=\frac{\operatorname{Sum}(j)^p}{\operatorname{Sum}(S)^p}\).
那么
考虑怎么处理这个转移系数。
按 \(|S|\) 从小到大转移,算出所有 \(f_S(|S|=i)\) 后变换回去再乘上转移系数。
时间复杂度 \(O(n^22^n)\),\(\rm TL=10s\sim 15s\),可以接受。
[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}\),即求
暴力 FWT 时间 \(O(nk\log k)\).
注意到 FWT 具有线性性,算出 \(fwt[f]\) 后令每一项的 \(x\leftarrow \sum_{i=1}^{n}x^i\) 后 IFWT 即可。
时间复杂度 \(O(k\log k+k\log n)\).
*[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\) 连边数量是奇数的点集。
即求
\(|a_S\cap T|\operatorname{mod}2\) 表示 \(S,T\) 之间边数的奇偶性。
枚举 \(f_S=x,g_T=y\),变成
考虑计算
记
有
FWTAND 即可。时间复杂度 \(O((n+m)2^\frac{n}{2})\).
最大点照着题解卡到了 1920ms.但是为什么那一篇可以只跑 1.2s.
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|)\),用欧拉降幂优化。
[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\) 的贡献系数,写为矩阵:
有 \(b=a\times c^{-1}\),可以得到
实现过程类似三进制下的 FWT。
[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\),即求
运算均为异或。
考虑 \(\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 即可。
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))\) 视为集合 \(S\) 二进制下 \(1\) 的最晚期望出现时间,\(E(\min(S))\) 视为 \(1\) 的最早期望出现时间。
怎么求 \(E(\min(S))\),其实满足选到了和 \(S\) 有交的数即可,那么
把这个变成无交,枚举补集 \(S'\) 的子集:
求出和式,FWTOR 即可。
*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\) 才行?不是很理解。