SGU 275 To xor or not to xor

题目链接http://acm.sgu.ru/problem.php?contest=0&problem=275

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=98837#problem/A

题目分类:高斯消元

题意:给定n个数,从中选择任意个数,使它们的异或值最大

题目分析:把每个数用二进制表示,要使异或值最大,要让高位尽量为1,用高斯消元判断高位是不是1

1. 根据数的二进制表示,建立方程组的矩阵,结果那列置为1。
2. 从下往上高斯消元(高位放下面),如果该行有未被控制的变元,则该行的结果一定为1,且该变元控制该行。
3. 从该行往上依次消掉(异或)该变元。
4. 如果该行没有可以用来控制的变元,如果最后一列是0,则该行结果也为1,否则该行结果为0。这里能抱着已用来控制的变元的系数全是0,因为在第3步时就消掉该行以上此列的0了,后面0与0以后还是0。所以如果最后一列是0, 即该行方程也可以成立,故结果为1。

建立方程:

a11x1+a21x2……=d[1]

a12x1+a22x2……=d[2]

……

代码:

#include<bits/stdc++.h>

using namespace std;

#define INF 0x3f3f3f3f

long long bit[100];
int a[100][110];
bool used[110];

int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    bit[0] = 1;
    for(int i = 1;i < 63;i++)
        bit[i] = 2*bit[i-1];
    int n;
    long long x;
    while(scanf("%d",&n) == 1)
    {
        for(int i = 0;i < n;i++)
        {
            cin>>x;
            for(int j = 0;j < 63;j++)
            {
                if(x & bit[62-j])
                    a[j][i] = 1;
                else a[j][i] = 0;
            }
        }
        for(int i = 0;i < 63;i++)
            a[i][n] = 1;
        memset(used,false,sizeof(used));
        long long ans = 0;
        for(int i = 0;i < 63;i++)
        {
            int x = -1;
            for(int j = 0;j < n;j++)
                if(a[i][j] && !used[j])
                {
                    x = j;
                    break;
                }
            if(x == -1 && a[i][n] == 0)
                ans += bit[62-i];
            else if(x != -1)
            {
                ans += bit[62-i];
                for(int k = i+1; k < 63;k++)
                    if(a[k][x])
                    {
                        for(int j = 0;j <= n;j++)
                            a[k][j] ^= a[i][j];
                    }
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}

 

posted @ 2015-11-10 23:30  Gssol  阅读(385)  评论(0编辑  收藏  举报