二进制线性基学习笔记
定义
定义(性质型定义) 定义线性基为其中的元素可以通过求异或和,得到原集合的元素任意求异或和得到的所有值的集合,且集合大小最小。
性质
线性基大小定理 线性基的大小 \(\le \log a_i\)。
我们把 \(a\) 的每一位取出来形成一个 \(n \times \log a_i\) 的矩阵。
线性基本质上是把这个矩阵看作系数矩阵后求出的简化阶梯矩阵。因为初始矩阵的各种组合对应了 \(a\) 的各种组合。且系数矩阵和简化阶梯矩阵等价。
于是线性基大小就是 \(\min(n, \log a_i) \le \log a_i\)。
线性基子集非零定理 线性基不存在异或和为 \(0\) 的子集。
设 \(p_a \oplus p_b \oplus p_c \oplus p_x=0\),则 \(p_a \oplus p_b \oplus p_c=p_x\),遂 \(p_x\) 是多余的,与定义矛盾。
做法
贪心求法的正确性 设线性基数组为 \(d_i\) 则下列操作得到的 \(d\) 去除 \(0\) 后是线性基:
- 对于每个 \(x\) 从高位到低位进行。
- 如果 \(x\) 的第 \(i\) 位为1,判断 \(d_i\) 是否为 \(0\)。如果是,\(d_i=x\) 并退出;如果不是,\(x=x \oplus d_i\) 然后重复此步。
如果 \(x\) 第 \(i\) 位为 \(1\) 且 \(d_i\) 这一位为 \(1\),那么显然这一位用 \(d_i\) 结合其它的可以表示。否则,这一位不需要表示。由此,所有的数都可以被我们表示出来,得证。
由此我们也可以得知:若 \(d_i\) 不为 \(0\),则 \(d_i\) 的最高的 \(1\) 位在第 \(i\) 位。
void insert(int x)
{for(int i = 55;i >= 0;i--){if((x >> i) & 1){if(d[i]) x ^= d[i];else{d[i] = x;return;}}}
}
应用
应用 1 求异或和的最大值。
考虑直接贪心解决即可。如果答案这一位是 \(1\),那么啥也不做。否则异或上即可。
int ansmx()
{int ans = 0;for(int i = 55;i >= 0;i--) if(!((ans >> i) & 1)) ans ^= d[i];return ans;
}
应用 2 求异或和的最大值。
直接输出 \(d\) 的最小值即可。