|
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;
}
|