线性基

…衆ロ難τιáo~ 提交于 2019-12-10 00:07:44

线性基是一种针对异或运算的工具。

线性基的定义:对于一个序列,我们构造一个集合,使得序列中的每一个数都可以有集合中的一些数异或起来得到。

 

构造方式

for(i=1;i<=n;i++)
{
	x=a[i];
	for(j=len;j>=1;j--)
		if((x>>(j-1))%2==1)
			if(d[j]==0){d[j]=x;break;}
			else x=x^d[j];
}

我们逐一加入序列中的数x。每加入一个数时,我们从len到1比较目前线性基中的数(j)。如果x的第j位为1,那么就判断一下d[j]是否有值,如果没有的话那么就将x插入在d[j],否则将x异或上d[j]。最终求出来的d就是当前序列的线性基。

证明如下:

1、如果x没有被加入,则一定是x被异或成了0,那么就一定存在d[a]^d[b]^d[c]...=x。从上式中我们可以看出x可以被d中的数异或得到。

2、如果x成功被加入,那么假设x在加入d之前异或了d[a]、d[b]、d[c]...,x插在了d[j],则x^d[a]^d[b]^d[c]...=d[j],所以x=d[a]^d[b]^d[c]...^d[j]。这样x又可以被d中的数异或得到了。

 

判断一个数是否能被序列中的数异或得到

假设判断的数为v,那么我们按照上面的方式将v加入d中,如果能成功加入那么v就不能被表示,如果不能加入那么v就可以被表示。

 

求异或的最大值

从高位到低位枚举d,如果当前异或d使答案更大的话那么就将ans异或上d,否则就不管他。

for(j=len;j>=1;j--)
	if((ans^d[j])>ans)ans=ans^d[j];

 

求异或的最小值

直接求d中的最小值即可。

 

另外还有求第k小和删除,我暂时还不会。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!