线性基(【洛谷3812】)
线性基(【洛谷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\n",G.Query(0));
return 0;
}