线性基学习笔记


是什么 

常用于处理线性无关最大异或和最小异或表示集(即最小能用多少个数的异或和表示出原集合中的数)等问题

线性基,是一个向量集合,是一种压缩向量集合的手段,因此可以降低复杂度。

具体而言,就是线性基里的若干向量通过线性操作表示出原集合的每一个元素,且线性基内部的向量全部线性无关

因此线性基内的向量个数仅为向量的维度n。

对于这个,我们从方程的角度去理解:

把每个向量看作一条方程,向量的每一维对于一个未知数

即m个n维向量,相当于m条n元方程

如果一条方程能被其他方程通过线性运算表示出来,那么它就可以被去掉。

最后的结果就是该集合的线性基

怎么做

构造线性基的过程可以类比高斯消元。

我们最终会把线性基中的向量集化为上三角式矩阵,如下图。

具体而言,每加入一个向量,我们就从上到下将该向量依次减去每一条向量,每减一次就将一个变量消掉,直到无法再消为止

这样就可以得到一个上三角矩阵了。

代码如下

vector vec;
int n,m;
bool insert(data x)
{
	int p1=1,p2=1;
	while(fabs(x.arr[p1])p2) continue;
		if(p1


扩展

处理异或和的线性基是线性基中的一种

就是把每个数看作一个向量,它的每一个二进制位看作一维,这样就把每个数变成了一个31维向量,注意构造过程中要特殊化处理。

代码如下

struct linerbase
{
	int val[32];
        //最小异或表示集即为val中不为0的项
	void insert(int x)
	{
		for(int i=31;i>=0;i--)
		{
			if(((x>>i)&1)==0) continue;
			if(!val[i])
			{
				val[i]=x;
				return;
			}
			x^=val[i];
		}
	}
	linerbase()
	{
		memset(val,0,sizeof(val));
	}
        //查询最大异或和
	int query(int x)
	{
		for(int i=31;i>=0;i--)	if((x^val[i])>x) x^=val[i];
		return x;
	}
};