线性基(【洛谷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;
}

posted @ 2018-03-16 16:48  小蒟蒻yyb  阅读(474)  评论(1编辑  收藏  举报