2014百度之星资格赛解题报告:Xor Sum

Xor Sum
时间限制: 1S     空间限制:64M
问题描述
Zeus 和 Prometheus 做了一个游戏,Prometheus给 Zeus 一个集合,集合中包含了N个正整数,随后 Prometheus 将向 Zeus 发起M次询问,每次询问中包含一个正整数 S ,之后 Zeus 需要在集合当中找出一个正整数 K ,使得 K 与 S 的异或结果最大。Prometheus为了让 Zeus 看到人类的伟大,随即同意 Zeus 可以向人类求助。你能证明人类的智慧么?
输入
输入包含若干组测试数据,每组测试数据包含若干行。
输入的第一行是一个整数TT < 10),表示共有T组数据。
每组数据的第一行输入两个正整数NM<1=N,M<=100000),接下来一行,包含N个正整数,代表 Zeus 的获得的集合,之后M行,每行一个正整数S,代表 Prometheus 询问的正整数。所有正整数均不超过2^32
输出
对于每组数据,首先需要输出单独一行”Case #?:”,其中问号处应填入当前的数据组数,组数从1开始计算。
对于每个询问,输出一个正整数K,使得KS异或值最大。
样例输入
2
3 2
3 4 5
1
5
4 1
4 6 5 6
3
样例输出
Case #1:
4
3
Case #2:
4

解题报告
由于每个正整数都不超过232次方,所以将每个正整数的二进制数字作为字符串插入到字典树中,对于每一个询问,只需要按照贪心的做法搜索字典树就行了。
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:\n", 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\n" , k);
                }
        }
        return 0;
}


posted @ 2014-05-22 00:11  HoseaLeo  阅读(129)  评论(0编辑  收藏  举报