Acdream Xor 简单数学

给定一个集合A,一个集合B,A,B元素个数相等,然后问是否存在一个数X使得A中的元素均与这个数进行按位异或操作后的结果为B集合,如果存在输出最小的数,不存在输出-1。

思路:由于给定的N为奇数,所以能够根据二进制位的最右边位确定唯一的分组,然后只需要判定这个分组是否合理即可。

分组是这样划分的,如有A、B两组数据,把A组根据末位0和1分成两组,B组同理划分,那么只有00配对或者是01配对,这有各组中数的个数确定。配对模式确定后,再通过30次判定即可。

#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
using namespace std;

const int MaxN = 100005;
int a[MaxN], b[MaxN], N;
int ans[40];
int st[4][MaxN];
int cnt[4], bit[4][40];
// N是奇数就好做了

int cal(int x, int b[]) {
    for (int i = 0; i < 30; ++i) {
        if ((x >> i) & 1) ++b[i];
    }
}

int judge(int i, int mode) {
    // 如果是模式0,即st0 与 st2 匹配 
    if (mode == 0) {
        if (bit[0][i] == bit[2][i] && bit[1][i] == bit[3][i]) return 0;
        else if (bit[0][i] == cnt[2]-bit[2][i] && bit[1][i] == cnt[3]-bit[3][i]) return 1;
        else return -1;
    } else { // 如果是模式1,即st0 与 st3匹配 
        if (bit[0][i] == bit[3][i] && bit[1][i] == bit[2][i]) return 0;
        else if (bit[0][i] == cnt[3]-bit[3][i] && bit[1][i] == cnt[2]-bit[2][i]) return 1;
        else return -1;
    } 
}

void gao() {
    for (int i = 0; i < 4; ++i) {
        memset(st[i], 0, sizeof (st[i]));
        memset(bit[i], 0, sizeof (bit[i]));
    }
    memset(ans, 0, sizeof (ans));
    memset(cnt, 0, sizeof (cnt));
    for (int i = 0; i < N; ++i) {
        if (!(a[i] & 1)) st[0][cnt[0]++] = i;
        else st[1][cnt[1]++] = i;
        if (!(b[i] & 1)) st[2][cnt[2]++] = i;
        else st[3][cnt[3]++] = i;
    }
    for (int i = 0; i < 4; ++i) {
        for (int j = 0; j < cnt[i]; ++j) {
            if (i < 2) cal(a[st[i][j]], bit[i]);
            else cal(b[st[i][j]], bit[i]);
        }
    }
    int mode = -1;
    // 由最低位的1的个数划分模式,由于N为奇数,所以划分的方式是唯一的 
    if (cnt[0] == cnt[2]) ans[0] = mode = 0;
    else if (cnt[0] == cnt[3]) ans[0] = mode = 1;
    if (mode == -1) {
        puts("-1");
        return;
    }
    for (int i = 1; i < 30; ++i) {
        ans[i] = judge(i, mode);
        if (ans[i] == -1) {
            puts("-1");
            return;
        }
    }
    int ret = 0;
    for (int i = 0; i < 30; ++i) {
        ret += ans[i] ? (1 << i) : 0;
    }
    printf("%d\n", ret);
}

int main() {
    while (scanf("%d", &N) == 1) {
        for (int i = 0; i < N; ++i) {
            scanf("%d", &a[i]);
        }
        for (int i = 0; i < N; ++i) {
            scanf("%d", &b[i]);
        }
        gao();
    }
    return 0;        
}

 

posted @ 2012-11-18 14:34  沐阳  阅读(323)  评论(2编辑  收藏  举报