参考题:https://www.luogu.com.cn/problem/P3812
作用
- 查询某个数是否能被一组数异或得到
- 查询一组数能够异或的到的最大/小值,第k大值
解释
本质上就是作用在 (01) 串的高斯消元,只不过消元的途径是异或。
比如一组数(二进制):
1010
1100
0011
建立线性基的过程是:
(egin{pmatrix}
0 & 0 & 0 & 0\
0 & 0 & 0 & 0\
0 & 0 & 0 & 0\
0 & 0 & 0 & 0\
end{pmatrix})
对第一个数:
从最高位开始扫,发现第一位就是 (0) ,故更新:
(egin{pmatrix} 1 & 0 & 1 & 0\ 0 & 0 & 0 & 0\ 0 & 0 & 0 & 0\ 0 & 0 & 0 & 0\ end{pmatrix})
对第二个数:
依然从最高位开始扫,发现第一位是 (1) ,所以第二个数要异或第一位对应的基底得到 (0110_{(2)}) ,继续扫,第二位是(0),故更新为:
(egin{pmatrix} 1 & 0 & 1 & 0\ 0 & 1 & 1 & 0\ 0 & 0 & 0 & 0\ 0 & 0 & 0 & 0\ end{pmatrix})
类似的,对第三个数,可以更新矩阵得到:
(egin{pmatrix} 1 & 0 & 1 & 0\ 0 & 1 & 1 & 0\ 0 & 0 & 1 & 1\ 0 & 0 & 0 & 0\ end{pmatrix})
可以发现上面整个过程就是通过异或来进行高斯消元。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=55;
ll base[N];
int main(){
int n; cin>>n;
while(n--){
ll k; cin>>k;
for(int j=N-1;~j;j--){
if(k&(1LL<<j)){
if(!base[j]) base[j]=k;
k^=base[j];
}
}
}
ll ans=0;
for(int j=N-1;~j;j--){
if((ans^base[j])>ans) ans=ans^base[j];
}
cout<<ans<<endl;
return 0;
}