• 集合


    【问题描述】

    小明非常喜欢数字。最近他的妈妈送给他了一个由n个非负整数组成的集合。小明非常喜欢和小刚玩。他立即决定把他n个数字中的一部分送给小刚。为了让游戏更加有趣,小明决定使得给她的数字集合满足如下条件:

    我们用x1表示小明的数字集合的xor值,用x2表示小刚的数字集合的xor值。要使得x1+x2尽可能地大。假如有多种划分集合的方法使得集合满足上述条件,小明就要让x1尽可能地小。

    帮助小明照上述方法划分集合。如果有多种合适的方法,就找出其中任意一种方法。请注意,小明将一部分数字给了小刚之后,他可能就没有任何剩余的数字了。反之亦然,小明也可以不给小刚任何数字。在这两种情况下,我们都假定空集的xor值为0。

    【输入格式】

    从文件set.in中输入数据。

    输入的第一行包含一个整数n,表示小明的妈妈给了他多少个数字。

    第二行包含n个用空格隔开的数字,保证它们都是不超过10^18的非负整数。

    【输出格式】

    输出到文件set.out中。

    输出一行,包含n个用空格隔开的整数,如果第i个数是1,则表示小明保留给出的第i个数字,如果第i个数是2,则表示小明把给出的第i个数字给了小刚。

    【样例输入】

    8

    1 1 2 2 3 3 4 4

    【样例输出】

    1 2 1 2 2 2 1 2

     

     

    【数据规模与约定】

    对于30%的数据,保证n<=10;

    对于60%的数据,保证n<=1000;

    对于100%的数据,保证n<=100000。

     

    这道题需要按位考虑。如果总体异或和的某一位是0,那么肯定分成的x1和x2这一位都是1。

    先考虑为0的,后考虑为1的是最优策略。

    相当于每一步我们都扔进去一个异或方程组,直接消元,线性相关肯定就扔掉了。

    用bitset压位一下就好了。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define M 100010
     4 #define LL long long
     5 inline LL read() {
     6     char ch = getchar(); LL x = 0, f = 1;
     7     while(ch < '0' || ch > '9') {
     8         if(ch == '-') f = -1;
     9         ch = getchar();
    10     }
    11     while('0' <= ch && ch <= '9') {
    12         x = x * 10 + ch - '0';
    13         ch = getchar();
    14     }
    15     return x * f;
    16 }
    17 LL A[M];
    18 bitset<100010> a[110];
    19 int pos[M];
    20 int res[M];
    21 int tot;
    22 int main() {
    23     int n; scanf("%d", &n);
    24     LL All = 0;
    25     for(int i = 0; i < n; ++ i) {
    26         A[i] = read();
    27         All ^= A[i];
    28     }
    29     for(int k = 0; k < 2; ++ k) {
    30         for(int i = 60; i >= 0; -- i) if((All >> i & 1) == k){
    31             ++ tot;
    32             for(int j = 0; j < n; ++ j) if((A[j] >> i & 1)){
    33                 a[tot][j] = 1;
    34             }
    35             a[tot][n] = k ^ 1;
    36             for(int j = 1; j < tot; ++ j) {
    37                 if(a[tot][pos[j]]) a[tot] ^= a[j];
    38             }
    39             pos[tot] = -1;
    40             for(int j = 0; j < n; ++ j) {
    41                 if(a[tot][j]) {
    42                     pos[tot] = j;
    43                     break;
    44                 }
    45             }
    46             if(pos[tot] == -1) {
    47                 -- tot; continue;
    48             }
    49             for(int j = 1; j < tot; ++ j) {
    50                 if(a[j][pos[tot]]) a[j] ^= a[tot];
    51             }
    52         }
    53     }
    54     for(int i = 1; i <= tot; ++ i) {
    55         res[pos[i]] = a[i][n];
    56     }
    57     for(int i = 0; i < n; ++ i) {
    58         printf("%d ", 2 - res[i]);
    59     }
    60 }
  • 相关阅读:
    java——base64 加密和解密
    BASE64Encoded() 方法报错说方法未定义
    java 实现HTTP连接(HTTPClient)
    如何关闭一些烦人的弹窗(总结)
    IDEA
    6、git和github
    5、预测和鉴定miRNA的靶基因
    4、在线blast比对结果解析(保守结构域)
    ASE分析
    3、Linux下配置Java环境
  • 原文地址:https://www.cnblogs.com/iamqzh233/p/10079281.html
Copyright © 2020-2023  润新知