问题:
洛谷P3812
给定一个长度为\(n\)的序列,值域\(2^50\),求在序列中选出若干个数的异或和最大值。
思路:
使用线性基,流程为,枚举\(n\)个数,每个数从二进制最高位向低位枚举,如果这个数含有这一位且这一位未放入任何数,直接放入,如果这个数有这一位但是放入了数,这个数就异或上已经放入的数。
首先证明原序列中的数能异或出的异或和和线性基中的完全等同,因为线性基的数都是原序列异或出来的,所以线性基中能组成的异或和原序列也可以,又因为在刚才的流程中原序列中的数不断地被线性基中的数异或,所以原序列中的数都可以被线性基的异或和表示,综上所述,原序列中的数能得出的异或和和线性基中的完全等同。
得到线性基数组\(a\),其有一个性质,\(a_i\)要么为\(0\),要么最高位为第\(i\)为,可以理解为流程中放不进去就异或是删掉最高位。
贪心每次找最高位让它为一。
代码:
#include<iostream>
#define int long long
using namespace std;
int n;
int a[100];
int b[100];
int ans=0;
signed main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=n;i++){
for(int j=60;j>=0;j--){
if((a[i]&(1ll<<j))!=0){
if(b[j]==0){
b[j]=a[i];
}
a[i]^=b[j];
}
}
}
for(int j=60;j>=0;j--){
if(b[j]!=0&&(ans&(1ll<<j))==0){
ans^=b[j];
}
}
cout<<ans;
return 0;
}
标签:基中,int,序列,异或,线性,放入
From: https://www.cnblogs.com/z-2-we/p/17875991.html