线性基

线性基

参考资料:

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小值

鸽子赶正在来的路上

原文地址:https://www.cnblogs.com/sssy/p/9183962.html