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;        

}

 

你可能感兴趣的:(数学)