数学/数论专题-学习笔记:线性基
1. 前言
线性基,是线性代数中的一个板块,专门处理异或问题。
注意作者是个 OIer,因此并不会涉及(或者是极少的)线性代数知识。
注意本文所讲线性基跟向量无关。
前置知识:二进制,位运算。
2. 详解
2.1 定义与性质
线性基的定义如下:
给出一个数列 \(a_1,a_2,...,a_n\),若一个序列 \(d_1,d_2,...,d_k\) 满足以下性质:
- 所有原数列中的元素能够异或出来的值 \(d\) 中的数也能异或出来。
- 满足性质 1 的前提下,\(d\) 中的数不能异或出 0。
- 满足性质 2 的前提下,\(d\) 中的数最少。
那么就称 \(d\) 是原序列 \(a\) 的一组线性基。
注意上述性质中的异或指的是从数列中选出一些数一起异或。
实际上任意数列 \(a\) 都有至少一组线性基。
2.2 构造线性基
这个方法需要用到一个性质:\(a \oplus b=c \Leftrightarrow a \oplus c=b\)。
首先考虑将所有 \(a_i\) 转成二进制,然后从二进制最高位开始扫,对于第 \(x\) 位,如果 \(d_x\) 不存在,那么 \(d_x=a_i\),否则 \(a_i \gets a_i \oplus d_x\),一个一个插入即可。
Code:
void add(LL x)
{
for (int i = 50; i >= 0; --i)
{
if (x & (1ll << i))
{
if (d[i] & x) x ^= d[i];
else { d[i] = x; break ; }
}
}
}
那么这份代码如何满足上述 3 个性质呢?
性质 1:原序列能够异或出来的数线性基也能够异或出来。
性质 2:线性基内的数不能异或出 0。
这两条性质都是根据 \(a \oplus b=c \Leftrightarrow a \oplus c=b\) 来证明的。
由于 \(x \oplus d_i = d_j \Leftrightarrow d_i \oplus d_j = x\),因此性质 1 得证。
性质 2 采用反证法:假设 \(d_i \oplus d_j \oplus d_k=0\),\(d_k\) 最晚插入。
这里只讨论 3 个数的理由是实际上你可以将 \(d_i\) 看成多个数异或。
上式等价于 \(d_i \oplus d_j= d_k\)。
于是根据代码,\(d_k\) 不应该被插入线性基,矛盾。
性质 3 的证明:
显然对于所有存在的 \(d_i\) 而言,第 \(i\) 位二进制位一定是 1。
既然如此,如果删去任何一个数,都会导致有一位二进制位空缺,因此这些数是必要的,同时又是最少的。
3. 应用
3.1 最大值问题
该问题的详述描述如下:给出数列 \(\{a_i\}\),从中选一些数使其异或结果最大。
根据线性基的性质 1,我们可以构造线性基。
构造之后直接暴力按照 \(d_i\) 从大到小枚举,然后看一下跟答案异或能否使答案变大,能就异或。
实际上就是一个贪心的思想。
为什么这样贪心是对的呢?
如果第 \(i+1\) 位通过异或变成了 1,即使 \(1-i\) 位通过异或都变成了 0,答案也一定是增大的。
因此贪心是正确的。
3.2 最小值问题
这个问题有两类:
第一类问题:问线性基能异或出的最小值。
这个直接就是最小的 \(d_i\),因为最小的 \(d_i\) 无论异或谁都会变大。
第二类问题:问原序列能异或出的最小值。
这个还需要看一下有没有元素插入失败,如果有就是 0,否则还是最小的 \(d_i\)。
3.3 第 k 小问题
该问题的详细描述如下:给出序列 \(\{a_i\}\),取出任意数进行异或,问能异或出的所有值的第 \(k\) 小。
首先我们需要对线性基做一个处理。
对于每一个 \(d_i\),如果 \(d_i\) 二进制表示第 \(j\) 位为 1,那么 \(d_i \gets d_{j-1} \oplus d_i\)。
然后对 \(k\) 做二进制拆分,如果第 \(i\) 位为 1,那么答案异或上 \(d_i\)。
这样做的正确性就是考虑到 \(d_i\) 实质作用是提供最高位的 1,因此只要所有 1 能够跟 \(k\) 对应答案就是第 \(k\) 小。
实际上转换后的线性基还是线性基。
3.4 异或和问题
详细描述:给出序列 \(\{a_n\}\),选若干个数异或,问可能的结果的和。
首先得出线性基,设大小为 \(s\),枚举每一个二进制位 \(d\),如果存在一个线性基中的数,该位为 1,那么这位的贡献是 \(2^d \times 2^{s-1}\),所有贡献加起来即可。
正确性证明:\(2^d\) 是这一位的值,\(2^{s-1}\) 是别的位能异或出的结果种数,保证结果种数互不相同是因为保证个数最小,此时就保证了不会出现两组不同的数,其异或值相同。
4. 总结
线性基的三大性质:
- 所有原数列中的元素能够异或出来的值线性基中的数也能异或出来。
- 线性基中的数不能异或出 0。
- 线性基中的数最少。
构造方式:首先考虑将所有 \(a_i\) 转成二进制,然后从二进制最高位开始扫,对于第 \(x\) 位,如果 \(d_x\) 不存在,那么 \(d_x=a_i\),否则 \(a_i \gets a_i \oplus d_x\),一个一个插入即可。
最大值问题:贪心从大到小求解。
最小值问题:最小 \(d_i\) 或者是 0。
第 \(k\) 小问题:转换线性基后直接二进制拆分。
异或和问题:枚举二进制位后算贡献 \(2^{d} \times 2^{s-1}\)。