Acdream Xor 简单数学
2012-11-18 14:34
351 查看
给定一个集合A,一个集合B,A,B元素个数相等,然后问是否存在一个数X使得A中的元素均与这个数进行按位异或操作后的结果为B集合,如果存在输出最小的数,不存在输出-1。
思路:由于给定的N为奇数,所以能够根据二进制位的最右边位确定唯一的分组,然后只需要判定这个分组是否合理即可。
分组是这样划分的,如有A、B两组数据,把A组根据末位0和1分成两组,B组同理划分,那么只有00配对或者是01配对,这有各组中数的个数确定。配对模式确定后,再通过30次判定即可。
思路:由于给定的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; }
相关文章推荐
- Round 3 G - 2-3 Trees ACdream - 1412 -组合数学-DP
- acdream.LCM Challenge(数学推导)
- Acdreamoj1115(数学思维称号)
- acdream 1025 简单dp
- 2016 Multi-University Training Contest 2 1001 Acperience (简单数学)
- Acdream 1065 同心树(数学)
- Acdreamoj1115(数学思维题)
- acdream.Bet(数学推导)
- acdream.A Very Easy Triangle Counting Game(数学推导)
- ACdream 简单数论 专题
- acdream.Triangles(数学推导)
- ACdream 1073 雷霆战机
- hdu 4430 Yukari's Birthday (简单数学 + 二分)
- hdu 2552 三足鼎立(简单数学)
- ACdreamXMUT新生摸底训练赛C - 娜娜梦游仙境系列——吃不完的糖果
- ACdream 1210 Chinese Girls' Amusement 大数+思维
- 全文搜索ElastacSearch笔记(1)-简单增删改查
- 程序员的数学--简单的读书笔记
- URAL 1158 AC自动机上的简单DP+大数
- 1714 ACdream王国的花店