线性基(【洛谷3812】)
题面
题目描述
给定n个整数(数字可能重复),求在这些数中选取任意个,使得他们的异或和最大。
输入输出格式
输入格式:
第一行一个数n,表示元素个数
接下来一行n个数
输出格式:
仅一行,表示答案。
输入输出样例
输入样例#1:
2
1 1
输出样例#1:
1
题解
线性基模板题
以下是线性基的有关内容
1.构建
对于当前要加入线性基的数(x)
不妨令(x)最高位的(1)在第(p)位
如果线性基中已经存在(a[p])
那么,(x=x xor a[p])继续处理
否则,(a[p]=x),结束操作
如果(x)在执行完插入操作后变成了(0),
证明(x)可以用线性基中的数的一个子集的异或和来表示
2.查询
查询某个数(x)与线性基中任意个数的异或和的最大值
从最高位开始,依次访问每个(a[i]),
如果(x xor a[i]>x),
直接令(x=x xor a[i]),继续操作即可
3.实现
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
inline ll read()
{
RG ll x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
int n;
struct xxj
{
ll p[60];
void insert(ll x)
{
for(int i=50;i>=0;--i)
{
if(!(x&(1ll<<i)))continue;
if(!p[i])p[i]=x;
x^=p[i];
}
}
ll Query(ll x)
{
for(int i=50;i>=0;--i)
x=max(x,x^p[i]);
return x;
}
}G;
int main()
{
n=read();
while(n--)G.insert(read());
printf("%lld
",G.Query(0));
return 0;
}