线性基
线性基
参考资料:
wfj_2048:https://www.cnblogs.com/wfj2048/p/6547789.html
Yveh : https://blog.csdn.net/qaq__qaq/article/details/53812883
关于向量空间与现行无关的东西,额...时间有限,一会还要补反演的题解,先咕着
具体应用概念:
概念
对于一个数集\(V\)定义异或运算,他的线性基是他的一个子集\(A\)(其实也不能这么说),A中所有数互相异或得到的集合等价于\(V\)中所有数互相异或的到的集合,也就是说,A可以看做是V的压缩
线性基的性质
1.设线性基的异或集合中不存在0,A是V中线性无关的极大子集。
2.线性基的异或集合中每个元素的异或方案唯一,其实与性质1等价。
3.线性基二进制最高位互不相同。
4.如果线性基是满的,它的异或集合为\([1,2^n−1]\)。
5.线性基中元素互相异或,异或集合不变。
如何维护
插入
插入一个数,从高位到低位枚举线性基中的元素
若插入的数在该二进制位有1,那么有两种操作
1:若线性基当前位置没有数,把当前位赋位x,break
2:否则,插入数异或当前位的数,继续匹配
可以看出,插入x的最终结果是:x被选入线性基中,或者x在最后变为0,也就是x可以被线性基中的数异或组合出来
for(int i = 1;i <= n;++ i) {
long long k = a[i];
for(int j = 60; ~j ;-- j) {
if(k & (1LL << j)) {
if(!b[j]) {b[j] = k;break;}
else k ^= b[j];
}
}
}
查询存在性
相当于插入的操作,如果x最后变成了0,说明x已经存在于线性基的异或集合中了。
查询最大值
从高位到低位扫描。如果异或当前线性基数能使得答案变大,那么就异或。
因为,线性基中保证每个数的的最高位位置唯一,从最高位开始贪心,要保证该位有值显然是最优,后面值得更新不会影响到前面
for(int j = 60;~j;-- j) {
if((ans ^ b[j]) > ans) ans ^= b[j];
}
合并两个线性基
暴力
查询k小值
鸽子赶正在来的路上