线性基学习笔记
基本思想
可以类比线性代数中的向量空间学习。
从二进制的角度看待每个数,每一位可以类比为向量空间的一维,每一维只有 $0$ 和 $1$ 两种取值。$n$ 个数就是 $n$ 个 $64$ 维的向量(long long
为例),它们构成了 $64$ 维向量空间的一个子空间。这个子空间中允许异或运算,两个向量相异或即每一维相异或。
线性基是一组数,构成这个子空间的一个基底,也即满足以下性质:
- 原集合的任一元素可由线性基中的一些元素相异或得到;
- 线性基是满足上述条件的最小集合;
- 线性基没有异或为 $0$ 的子集:否则违背第二条;
- 线性基的选取元素方案不同,异或值不同:否则存在子集异或为 $0$.
线性基的构造方式:
设 $p[]$ 是存储线性基中的数组,$p[i]$ 存储最高位为 $i$ 的数字。向线性基中插入一个数 $x$ 时,从高位向低位扫描,当扫到第 $k$ 位时,若 $p[k]$ 为 $0$,则 $p[k]$ 置为 $x$;否则 $x$ 异或上 $p[k]$. 代码如下:
1 | inline void insert(LL x){ |
原因是:若 $p[k]=0$,则线性基中目前无法将 $x$ 异或出来,必须将 $p[k]$ 置为 $x$;否则,可以选出 $p[k]$ 将第 $k$ 位搞定,然后 $x$ 异或上 $p[k]$ 继续去匹配。
本质上其实和线性代数中初等行变换化上三角矩阵是一个道理,把 $p[]$ 数组一行一行写下来,大的在上,小的在下,就形成了一个上三角矩阵(不管不存在的维)。
有些题目可能还要化标准型矩阵,需要进行高斯消元:
1 | inline void norm(){ |
模板
1 |
|
练习
luoguP3812 【模板】线性基
任取数使得异或值最大。
从大到小考虑线性基中的数,若异或上它之后答案变大则异或,否则不异或。
1 |
|
hdu3949 XOR
求第 $k$ 小异或值。
设线性基中基向量从大到小依次为 $\mathbf{v_0,v_1,\cdots,v_{m-1}}$(已经标准化了之后),则这个线性空间中第 $k=(b_x\cdots b_0)_2$ 小的数为
根据二进制不难证明。
1 |
|
[BJWC2011]元素
按法力从大到小排序,依次往线性基中插入元素时,若能插入则加上它的法力;否则扔掉。
贪心正确性:如果某个子集异或为 $0$,必然需要扔掉一个矿石,当然是扔掉法力最小的矿石啦。无法插入线性基的意义即它与之前的某些矿石形成的集合异或为 $0$,排序后它就是最小法力的矿石,不管它即可。
1 |
|
[TJOI2008]彩灯
输出子空间的大小,即 $2$ 的线性基大小次幂即可。
1 |
|
[SCOI2016]幸运数字
倍增lca + 线性基
1 |
|
[WC2011]最大XOR和路径
从一个点出发,到某个圈绕一圈之后再原路返回,就白嫖到了这个圈的异或和。所以把所有圈的异或和丢进线性基,再任意找一条从 $1$ 到 $n$ 的路径在线性基中询问即可。(任意找的原理是:即使当前路径不是最优的,最优路径一定会与它形成了若干圈,异或这些圈就能自动修正成最优路径)
1 |
|