【高斯消元】[SGU275]To xor or not to xor

来源:互联网 发布:监控干扰器软件 编辑:程序博客网 时间:2024/06/02 11:09

题目大意

就是给你n个数然后从中选择一些出来异或求异或可得到的最大值

题目分析

根据题目我们可以发现假设我们的答案是Ans=d1d2d3d4这里的di均为0或者1(这里不是乘法哦)那么我们可以从高位一直枚举获得我们当前的Ans检验是否可行但是如果直接检验的复杂度是O(2n)这里n最大为63因为263>=1018那么我们显然超时,所以我们可以从高枚举到地位,同时每枚举一位检验可行性,1或者0那么对于第i位显然影响它的只有给出的数中&(1<<(i-1))有>0的才会影响,那么我们可以根据这个列出方程,检查可行性就变成了检查当前的是否有解

代码

离线算法

#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>using namespace std;const int MAXN = 100;long long A[MAXN+10];long long Bits[MAXN+10];long long T[MAXN+10][MAXN+10], Ma[MAXN+10][MAXN+10];bool C[MAXN+10], vis[MAXN+10];int x[MAXN+10];bool check(int n, int m, int k){    int row, col;    memset(x, 0, sizeof x);    memset(vis, 0, sizeof vis);    for(row = col = 1;row<=k&&col<=n;row++, col++){        if(!Ma[row][col])        for(int j=row+1;j<=k;j++){            if(Ma[j][col]){                swap(Ma[j], Ma[row]);                break;            }        }        if(!Ma[row][col]){            row--;            continue;        }        for(int i=row+1;i<=k;i++){            if(Ma[i][col]){                for(int j=col;j<=m;j++)                    Ma[i][j] ^= Ma[row][j];            }        }    }    //row--;    for(int i=row;i<=k;i++)        if(Ma[i][m])            return false;    return true;}int main(){    int n;    scanf("%d", &n);    for(int i=1;i<=n;i++)        scanf("%I64d", &A[i]);    Bits[1] = 1;    memset(T, 0, sizeof T);    for(int i=2;i<=60;i++)        Bits[i] = Bits[i-1] << 1;    for(int i=60;i>=1;i--){        T[i][n+1] = 1;        for(int j=1;j<=n;j++)            if((Bits[i] & A[j]) > 0)                T[i][j] = 1;        memcpy(Ma, T, sizeof Ma);        if(!check(n, n+1, 60))            T[i][n+1] = 0;    }    long long ans = 0;    for(int i=1;i<=60;i++)        ans += 1LL * T[i][n+1] * Bits[i];    printf("%I64d\n", ans);    return 0;}/*311 9 51011 = 111001 = 9101 = 51 1 1 10 1 1 00 0 1 10 0 0 1*/

在线算法

#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>using namespace std;const int MAXN = 100;long long A[MAXN+10], Bits[MAXN+10], Ma[MAXN+10][MAXN+10], C[MAXN+10], T[MAXN+10], ans, n;bool solve(int n, int m, int k){    for(int i=1;i<=m;i++)        if(Ma[n][i]){            if(C[i]){                for(int j=i;j<=k;j++)                    Ma[n][j] ^= Ma[C[i]][j];            }else{                C[i] = n;                return true;            }        }    return Ma[n][k] == 0;}int main(){    scanf("%I64d", &n);    for(int i=1;i<=n;i++) scanf("%I64d", &A[i]);    Bits[1] = 1;    for(int i=2;i<=60;i++) Bits[i] = Bits[i-1] << 1;    for(int i=60;i>=1;i--){        memset(T, 0, sizeof T);        for(int j=1;j<=n;j++){            if((A[j] & Bits[i]) > 0)                T[j] = 1;        }        memcpy(Ma[i], T, sizeof Ma[i]);        Ma[i][n+1] = 1;        if(solve(i, n, n+1))            ans += Bits[i];    }    printf("%I64d\n", ans);    return 0;}
0 0