线性基学习笔记
线性基是干嘛的呢?
给定n个数,求所有数的异或和最大是多少?
求解这类问题的时候,就需要线性基了
个人感觉线性基本身就一种贪心。
首先定义\(base[i]\)表示最高位1在i位的数是什么
对于新进来的数\(tmp\),我们先找出他最高位上的1,假设为第\(j\)位,然后看一下\(base[j]\)有没有数,如果没有,直接将它赋值成\(tmp\),如果有,那就\(tmp^=base[j]\)就有点像高斯消元 对,把\(tmp\)这位的1消去(或者说,这个数去掉这位1之后,还能对哪些\(base\)作贡献),那么我们考虑,经过这个处理,\(tmp\)要么被加入了base,要么变成了0(就是他可以被之前的数异或得到)
求\(max\)的时候,我们就贪心即可
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long
using namespace std;
inline ll read()
{
ll x=0,f=1;char ch=getchar();
while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
ll n,tmp;
ll base[110];
int main()
{
n=read();
for (int i=1;i<=n;i++){
tmp=read();
for (int j=63;j>=0;j--)
{
if (tmp & (1LL << j))
{
if (!base[j])
{
base[j]=tmp;
break;
}
tmp^=base[j];
}
}
}
ll ans=0;
for (int i=63;i>=0;i--)
{
if (ans<(ans ^ base[i])) ans^=base[i];
}
cout<<ans;
return 0;
}
这里补充一个线性基的性质:
1>同时线性基的任何一个非空子集都不会使得其\(xor\)和为0
2>果有很多个数,我们可以构出这些数的线性基,那么这个线性基可以通过互相xor,能够构出原来的数可以相互xor构出的所有的数。就可以减少判断的时间和次数。