展开
题目背景
这是一道模板题。
题目描述
给定n个整数(数字可能重复),求在这些数中选取任意个,使得他们的异或和最大。
输入格式
第一行一个数n,表示元素个数
接下来一行n个数
输出格式
仅一行,表示答案。
输入输出样例
输入 #1复制
2
1 1
输出 #1复制
1
说明/提示
1 \leq n \leq 50, 0 \leq S_i \leq 2 ^ {50}1≤n≤50,0≤Si≤250
感谢这位博主的文章
全面解析的博客(原理)好文章
线性基模板题
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1005;
struct L_B
{
LL d[65], p[65];
int cnt;
void init()
{
memset(d,0,sizeof(d));
memset(p,0,sizeof(p));
cnt = 0;//线性基大小 ,子集异或和的种类为2^cnt
} // 1e18以内的数都适用.
bool Insert(LL val)
{
for (int i = 60 ; i >= 0 ; i --)
{
if (val & (1LL << i))
{
if (!d[i])
{
d[i]=val;
break;
}
val^=d[i];
}
}
if(val>0) cnt++;
return val > 0;
// 可判断val是否存在于线性基当中.
}
LL query_max()
{
LL res = 0;
for (int i = 60 ; i >= 0 ; i --)
{
if ((res^d[i]) > res)
res ^= d[i];
}
return res;
}
LL query_min() // 应该预先判断能否是0的情况..QAQ
{
for (int i = 0 ; i <= 60 ; i ++)
{
if (d[i])
return d[i];
}
return 0;
}
void rebuild() // 用于求第k小值.需要先进行独立预处理
{
for (int i = 60 ; i >= 0 ; i --)
{
for (int j = i-1 ; j >= 0 ; j --)
{
if (d[i] & (1LL<<j))
d[i] ^= d[j];
}
}
cnt=0;
for (int i = 0 ; i <= 60 ; i ++)
{
if (d[i])
p[cnt++]=d[i];
}
}
LL kthquery(LL k) // 注意判断原序列异或出0的情况, 此时应该将k -- 在进行后面的操作.
{
LL res = 0;
if (k >= (1LL << cnt))
return -1;
for (int i = 60 ; i >= 0 ; i --)
{
if (k & (1LL<<i))
res ^= p[i];
}
return res;
}
void Merge(const L_B &b) // 把b这个线性基插入到当前这个线性基中.
{
for (int i = 60 ; i >= 0 ; i --)
if (b.d[i])
Insert(b.d[i]);
}
}lb;
LL a[N];
int main()
{
int n;
scanf("%d",&n);
lb.init();
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
lb.Insert(a[i]);
}
cout<<lb.query_max()<<endl;
return 0;
}