Xor Sum
时间限制: 1S 空间限制:64M
问题描述
Zeus 和
Prometheus 做了一个游戏,Prometheus给 Zeus 一个集合,集合中包含了N个正整数,随后 Prometheus 将向 Zeus 发起M次询问,每次询问中包含一个正整数 S ,之后 Zeus 需要在集合当中找出一个正整数 K ,使得 K 与 S 的异或结果最大。Prometheus为了让 Zeus 看到人类的伟大,随即同意 Zeus 可以向人类求助。你能证明人类的智慧么?
输入
输入包含若干组测试数据,每组测试数据包含若干行。
输入的第一行是一个整数T(T < 10),表示共有T组数据。 每组数据的第一行输入两个正整数N,M(<1=N,M<=100000),接下来一行,包含N个正整数,代表 Zeus 的获得的集合,之后M行,每行一个正整数S,代表 Prometheus 询问的正整数。所有正整数均不超过2^32。 输出
对于每组数据,首先需要输出单独一行”Case
#?:”,其中问号处应填入当前的数据组数,组数从1开始计算。
对于每个询问,输出一个正整数K,使得K与S异或值最大。 样例输入
2
3 2
3 4 5
1
5
4 1
4 6 5 6
3
样例输出
Case #1:
4
3
Case #2:
4
解题报告
由于每个正整数都不超过2的32次方,所以将每个正整数的二进制数字作为字符串插入到字典树中,对于每一个询问,只需要按照贪心的做法搜索字典树就行了。
1. 将所有数字转为二进制。
2. 将集合中的所有二进制数变为一棵二叉树,左节点代表这一位为0,右节点代表1。
3. 对每一个询问,在这课二叉树上查询,如果这一位为0并且右孩子不为空,则往右走,否则往走左。最终到达叶子节点经过的路径就是所求的数的二进制表示。
解题代码: #include <iostream> #include <cstdio> #include <cstdlib> #define LENGTH 32 #define MAXN 100000 using namespace std; typedef struct node{ node *next[2]; bool flag; }; node Head; node arr[LENGTH * MAXN]; int nodeCount; node *GetNewNode(){ if (nodeCount >= LENGTH * MAXN) { printf("ERROR : node count full!"); exit(1); } arr[nodeCount].next[0] = NULL; arr[nodeCount].next[1] = NULL; arr[nodeCount].flag = false; return &(arr[nodeCount++]); } void Init(){ nodeCount = 0; Head.next[0] = NULL; Head.next[1] = NULL; Head.flag = false; } void insertNode(unsigned int num){ node *p = &Head; int temp; for (int i = LENGTH - 1; i>=0; i--){ if (((1<<i)&num) != 0){ temp = 1; } else { temp = 0; } if (p->next[temp] == NULL){ p->next[temp] = GetNewNode(); } p = p->next[temp]; } p->flag = true; } unsigned int searchNode(unsigned int s){ unsigned int k; node *p = &Head; int temp; k = 0; for (int i = LENGTH - 1; i>=0 ;i--){ if (((1<<i)&s) != 0){ temp = 0; } else { temp = 1; } if (p->next[temp] == NULL){ k = (k << 1) + (temp ^ 1); p = p->next[temp ^ 1]; } else { k = (k << 1) + temp; p = p->next[temp]; } } return k; } int main(){ int n , m ; unsigned int k , s; Init(); int case_count = 0; scanf("%d", &case_count); int case_index = 0; while ((case_count--) && scanf("%d%d" , &n , &m) != EOF){ case_index++; printf("Case #%d: ", case_index); Init(); for (int i = 0; i < n; i++){ scanf("%u",&k); insertNode(k); } for (int i = 0; i < m; i++){ scanf("%u" , &s); k = searchNode(s); printf("%u " , k); } } return 0; } |