zoukankan      html  css  js  c++  java
  • 集合

    【问题描述】

    小明非常喜欢数字。最近他的妈妈送给他了一个由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 }
  • 相关阅读:
    django 项目需要注意的一些点
    VUE之路
    Oracle 表格碎片的查看方法
    RHEL 6.x or 7.x 使用分区绑定ASM 磁盘的方法
    RMAN 修复主库 nologging 操作导致物理备库的坏块
    Oracle 数据库19c 回退降级到 11.2.0.4 方案
    如何评估oracle 数据库rman全备和增量备份大小
    在将Oracle GI和DB升级到19c或降级到以前的版本之前需要应用的补丁 (Doc ID 2668071.1)
    Oracle 数据库坏块处理
    opatch auto 安装11.2.0.4.20190115 PSU遇到 OUI-67133: Execution of PRE script failed,with returen value 1 报错
  • 原文地址:https://www.cnblogs.com/iamqzh233/p/10079281.html
Copyright © 2011-2022 走看看