线性基是一种针对异或运算的工具。
线性基的定义:对于一个序列,我们构造一个集合,使得序列中的每一个数都可以有集合中的一些数异或起来得到。
构造方式
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小和删除,我暂时还不会。
来源:CSDN
作者:chiyankuan
链接:https://blog.csdn.net/chiyankuan/article/details/103464692