线性基讲解:
视频:
https://www.bilibili.com/video/BV1A7411j7eX?from=search&seid=18060346418081718473
blog:
To xor or not to xor
The sequence of non-negative integers A1, A2, ..., AN is given. You are to find some subsequence Ai1, Ai2, ..., Aik (1 <= i1 < i2 < ... < ik <= N) such, that Ai1 XOR Ai2 XOR ... XOR Aik has a maximum value.
Input
The first line of the input file contains the integer number N (1 <= N <= 100). The second line contains the sequence A1, A2, ..., AN (0 <= Ai <= 10^18).
Output
Write to the output file a single integer number -- the maximum possible value of Ai1 XOR Ai2 XOR ... XOR Aik.
Sample test(s)
Input
3
11 9 5
11 9 5
Output
14
Author: | Michael R. Mirzayanov |
Resource: | ACM ICPC 2004-2005, NEERC, Southern Subregional Contest |
Date: | Saratov, October 7, 2004 |
sourse:SGU-275
一个经典的求子集异或最大的问题,就是把每个都插入线性基,如果用的方法是在插入的时候消掉其他元素的该位1,那么久在计算结果的时候直接把线性基的所有元素异或。如果插入的方法是在插入时直接插入不做处理,那么每次更新计算结果的时候if(ans^p[i]>ans) ans^=p[i]即可
这里是在插入之后做了处理,就是消掉了其他行的1。(也是高斯消元的思想)
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1e5+5;
typedef long long ll;
ll a[maxn],p[maxn],nubcnt;//a存放所有输入,p是线性基
void guass(int n)//这个函数是把所有的元素都插入了线性基 ,是个离线算法
{
memset(p,0,sizeof(p));
for(int i=1;i<=n;i++)
{
for(int j=63;j>=0;j--)
{
if((a[i]>>j)&1)
{
if(p[j]) a[i]^=p[j];
else
{
p[j]=a[i];
break;
}
}
}
}
for(int i=63;i>=0;i--)//这里是所有元素插入完毕之后再一起处理,消元
{
if(!p[i])
continue;
for(int j=i+1;j<=62;j++)
{
if((p[j]>>i)&1) p[j]^=p[i];
}
}
}
int main()
{
int t,n,q;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
guass(n);
ll ans=0;
for(int i=0;i<=63;i++)//把所有线性基里的元素异或就是最大值
ans^=p[i];
printf("%lld\n",ans);
return 0;
}
2021.8.24