【高斯消元】[SGU275]To xor or not to xor
题目大意
从N个数中选出任意个数,使XOR和最大
分析
我们贪心地思考这道题,每次,我们从最高位开始枚举答案的每一位,并且总是尝试使这一位为1,并和前面所有的方程联立求解,由于数据最大为
解法
算法1:在线高斯消元法
当然,有一种求异或方程的在线算法,新增加的方程,和前面的方程联立求解的时候只需要
如果再加上压位优化,复杂度为
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long LL;
typedef unsigned int uint;
#define MAXN 100
#define D 32
const int equ=63;
int n,var,row;
LL b[MAXN+10],ans,c[MAXN+10];
unsigned int a[equ+10][4];
template<class T>
void Read(T &x){
char c;
while(c=getchar(),c!=EOF)
if(c>='0'&&c<='9'){
x=c-'0';
while(c=getchar(),c>='0'&&c<='9')
x=x*10+c-'0';
ungetc(c,stdin);
return;
}
}
void read(){
Read(n);
int i,j;
for(i=0;i<n;i++)
Read(b[i]);
var=n;
for(i=1;i<=equ;i++)
for(j=0;j<var;j++)
a[i][j/D]|=((b[j]>>(equ-i))&1)<<(j%D);
}
void gaussian_elimination(){
int i,j,qv1=var/D,qv2=var%D;
for(row=1;row<=equ;row++){
a[row][qv1]|=1<<qv2;
for(i=0;i<var;i++)
if(a[row][i/D]&(1<<(i%D))){
if(!c[i]){
c[i]=row;
break;
}
else if(c[i])
for(j=0;j<4;j++)
a[row][j]^=a[c[i]][j];
}
ans<<=1;
if(i==var&&(a[row][qv1]&(1<<qv2)))
a[row][qv1]=0;
else
ans|=1;
}
}
int main()
{
read();
gaussian_elimination();
printf("%I64d",ans);
}
算法2:利用高斯约当消元法的性质
我们把刚刚的算法一的矩阵(不包括常数项)逆时针旋转90°,即每一行为一个数字,每一列为每一位。
我们发现,只要我们做高斯约当消元,就可以很容易的保证当前列的异或和为一。所以,我们做完高斯消元后,将得到的矩阵一行一行的异或起来,就能得到答案。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 100
typedef long long LL;
int n,equ,var=64,row;
LL a[MAXN+10],ans;
template<class T>
void Read(T &x){
char c;
while(c=getchar(),c!=EOF)
if(c>='0'&&c<='9'){
x=c-'0';
while(c=getchar(),c>='0'&&c<='9')
x=x*10+c-'0';
ungetc(c,stdin);
return;
}
}
void read(){
Read(n);
equ=n;
for(int i=1;i<=n;i++)
Read(a[i]);
}
void gauss_jordan(){
int i,col;
for(row=col=1;row<=equ&&col<=var;row++,col++){
if(!(a[row]>>(var-col))&1)
for(i=row;i<=n;i++)
if(a[i]>>(var-col)&1){
swap(a[i],a[row]);
break;
}
if(!(a[row]>>(var-col))&1){
row--;
continue;
}
for(i=1;i<=equ;i++)
if(i!=row&&(a[i]>>(var-col))&1)
a[i]^=a[row];
}
row--;
}
void print(){
for(int i=1;i<=row;i++)
ans^=a[i];
printf("%I64d",ans);
}
int main()
{
read();
gauss_jordan();
print();
}