• SGU 275. To xor or not to xor (高斯消元法)


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

    题意:给你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]

    ……

    很好的题目、

     1 /* ***********************************************
     2 Author        :kuangbin
     3 Created Time  :2014-1-31 0:48:47
     4 File Name     :E:2014ACMSGUSGU275.cpp
     5 ************************************************ */
     6 
     7 #include <stdio.h>
     8 #include <string.h>
     9 #include <iostream>
    10 #include <algorithm>
    11 #include <vector>
    12 #include <queue>
    13 #include <set>
    14 #include <map>
    15 #include <string>
    16 #include <math.h>
    17 #include <stdlib.h>
    18 #include <time.h>
    19 using namespace std;
    20 
    21 long long bit[100];
    22 int a[100][110];
    23 bool used[110];
    24 
    25 int main()
    26 {
    27     //freopen("in.txt","r",stdin);
    28     //freopen("out.txt","w",stdout);
    29     bit[0] = 1;
    30     for(int i = 1;i < 63;i++)
    31         bit[i] = 2*bit[i-1];
    32     int n;
    33     long long x;
    34     while(scanf("%d",&n) == 1)
    35     {
    36         for(int i = 0;i < n;i++)
    37         {
    38             cin>>x;
    39             for(int j = 0;j < 63;j++)
    40             {
    41                 if(x & bit[62-j])
    42                     a[j][i] = 1;
    43                 else a[j][i] = 0;
    44             }
    45         }
    46         for(int i = 0;i < 63;i++)
    47             a[i][n] = 1;
    48         memset(used,false,sizeof(used));
    49         long long ans = 0;
    50         for(int i = 0;i < 63;i++)
    51         {
    52             int x = -1;
    53             for(int j = 0;j < n;j++)
    54                 if(a[i][j] && !used[j])
    55                 {
    56                     x = j;
    57                     break;
    58                 }
    59             if(x == -1 && a[i][n] == 0)
    60                 ans += bit[62-i];
    61             else if(x != -1)
    62             {
    63                 ans += bit[62-i];
    64                 for(int k = i+1; k < 63;k++)
    65                     if(a[k][x])
    66                     {
    67                         for(int j = 0;j <= n;j++)
    68                             a[k][j] ^= a[i][j];
    69                     }
    70             }
    71         }
    72         cout<<ans<<endl;
    73     }
    74     return 0;
    75 }
  • 相关阅读:
    linux下解除端口占用
    设计模式(二)观察者模式
    设计模式(一) 策略模式
    loj #6235. 区间素数个数
    loj #2013. 「SCOI2016」幸运数字
    loj #6014. 「网络流 24 题」最长 k 可重区间集
    loj #6013. 「网络流 24 题」负载平衡
    loj #2255. 「SNOI2017」炸弹
    loj #2051. 「HNOI2016」序列
    loj #6122. 「网络流 24 题」航空路线问题
  • 原文地址:https://www.cnblogs.com/kuangbin/p/3536693.html
Copyright © 2020-2023  润新知