线性基
参考资料
例题
给定 个整数(数字可能重复),求在这些数中选取任意个,使得他们的异或和最大。 给定 个可重复的整数,选取任意个数,使得它们的异或和最大。 将每个整数视作 中的一个 维向量。在 上,加法 等价于按位异或 。 因此,问题可转化为:给定 个向量,选择若干个相加,使结果的二进制数值尽可能大。 在线性代数中,这组向量张成一个线性空间。 我们构造它的 线性基(一组两两线性无关且能生成整个空间的最小集合),再利用线性基 高位优先 的结构,贪心求出最大异或值。 维护数列 ,其中 表示最高位在第 位为 的基向量(若不存在则为 )。 插入整数 的过程如下:从高位到低位依次检查,如果 的第 个二进制位为 : 若最终 ,说明它可以由已有基向量异或得到(线性相关),无需加入基向量。 令 ,从高位到低位依次判断,尝试用基向量 增大答案: 数列 始终是一组能够张成原集合的基: 从高位到低位的顺序保证: 因此该贪心过程能得到全局最优解。题解
参考资料
题意简述
解题思路
思想
构造
查询
证明
参考代码
#include <bits/stdc++.h>
using namespace std;
using ull=unsigned long long;
const int N=64;
ull p[N];
void insert(ull x)
{
for(int i=N-1;i>=0;i--)
{
if(x>>i&1)
{
if(!p[i])
{
p[i]=x;
return;
}
x^=p[i];
}
}
}
ull query()
{
ull res=0;
for(int i=N-1;i>=0;i--)
{
res=max(res,res^p[i]);
}
return res;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
ull t;
cin>>t;
insert(t);
}
cout<<query()<<'\n';
return 0;
}