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

题目大意

就是给你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;
}
/*
3
11 9 5
1011 = 11
1001 = 9
101 = 5

1 1 1 1
0 1 1 0
0 0 1 1
0 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;
}

posted on 2016-01-31 00:45  JeremyGuo  阅读(208)  评论(0编辑  收藏  举报

导航