线性基学习笔记
定义:对于 \([0,2^M)\) 之间的数集 \(A\) ,可以由集合 $ D$ 中的数异或得来,且\(|D|\)最小化,则称 \(D\) 是 \(A\) 的一组线性基
注意到线性基不唯一
异或的基本性质:
线性基性质:
性质一:线性基的元素不能互相表出(线性无关)
证明:如果存在 \(d_i=d_{a_1}\oplus d_{a_2} \cdots \oplus d_{a_n}\)
则如果在表出时有用到 \(d_i\) ,可将其替换为\(d_{a_1}\oplus d_{a_2} \cdots \oplus d_{a_n}\) ,与线性基最小性矛盾
性质二:线性基的元素无法表出 \(0\)
证明:\(d_{a_1}\oplus d_{a_2} \cdots \oplus d_{a_n}=0\)
等价于 \(d_{a_2} \oplus d_{a_3} \cdots \oplus d_{a_n}=d_{a_1}\)
与性质一矛盾
性质三:线性基表出元素互不相同
证明:如果有两个线性基的子集异或和 \(A = B\),那么同上处理
\(A \oplus B = 0\)
而 \(A \oplus B\) 也一定为 \(D\) 的子集,与性质二矛盾
性质四:总是存在一组线性基,使每一个 \(d_i\) 的最高位的位置互不相同
证明:首先由 \(|D|\) 的最小性知所有的线性基大小相等
对于两个最高位在同一位的数 \(a\) ,\(b\) ,将 \(a\) 替换为 \(a \oplus b\) ,此时依然能够表出所有数,但是最高位在同一位的数不存在了
由此可知总能构造出一种满足条件的线性基
线性基求解
由性质四,可以得出一种动态构造满足性质四特殊线性基的算法:
设 \(p_i\) 表示二进制最高位为 \(i\) 的线性基元素
由性质四知道 \(p_i\) 唯一,标出了一个满足性质四的线性基
考虑添加元素 \(x\) 到 \(D\) 中,逐位考虑 \(x\) 为一的位置
首先对于全局最高位,如果 \(x\) 此位为一:
\(p_M=0\) 时,那么此时线性基无论如何异或都无法得到 \(x\) ,直接 \(p_M=x\),完成算法退出
否则 \(i\) 只能必须由 \(p_M\) 异或其他数表出,因为已经没有其他元素最高位比 \(p_M\) 高,为了方便后续操作,将插入目标改为 \(x \oplus p_M\)
如果 \(x\) 此位为零,则此位没有影响,不考虑
注意到此时已经考虑完了最高位后,后续不会再对最高位产生影响,相当于去掉最高位的子问题,将下一位看做最高位,继续插入修改后的 \(x\)
实现:
void ins(ll x){
for (int i=63; i>=0; i--)
if ((x>>i)&1) {
if (!d[i]){d[i]=x;break;}
x^=d[i];
}
}
单次插入时间复杂度 \(O(M)\) ,共计 \(O(NM)\)
另外一种求线性基的办法是矩阵高斯消元
我们考虑每个 \(a_i\) ,将其二进制分解写成矩阵形式
可以知道,异或操作是模二意义下的加法,即模二意义下的初等行变换
高斯消元为上三角矩阵
去掉为零的行,由于异或操作可逆,可知这是原集合的线性基
此时每一行恰有一个主元,满足性质四
复杂度 \(O(NM^2)\) ,实现略
线性基应用
1.查询某个数够被 \(A\) 中的元素异或表出:
直接用第一种方式尝试插入该数,如果最终没有发生修改,那么返回 True
2.查询所有能被 \(A\) 中元素异或表出的数中第 \(k\) 大的数:
拍
同样考虑最高位,
首先处理一下原来的满足性质四的线性基,要保证除了 \(p_i\) 外其他所有线性基元素的第 \(i\) 位为零,直接将不为零的位异或上已经处理过的 \(p_j(j<i)\) 即可
对于 \(p_M\),由于所有数异或上 \(p_M\) 一定比原本大,那么将 \(k\) 与 \(2^{M-1}\) 比较,就可以知道需不需要异或 \(p_M\)
继续按位考虑子问题即可
3.查询最大/最小异或和
仿照2进行贪心即可