Xor Sum
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 132768/132768 K (Java/Others)Total Submission(s): 712 Accepted Submission(s): 342
Problem Description
Zeus 和 Prometheus 做了一个游戏,Prometheus 给 Zeus 一个集合,集合中包含了N个正整数,随后 Prometheus 将向 Zeus 发起M次询问,每次询问中包含一个正整数 S ,之后 Zeus 需要在集合当中找出一个正整数 K ,使得 K 与 S 的异或结果最大。Prometheus 为了让 Zeus 看到人类的伟大,随即同意 Zeus 可以向人类求助。你能证明人类的智慧么?
Input
输入包含若干组测试数据,每组测试数据包含若干行。
输入的第一行是一个整数T(T < 10),表示共有T组数据。
每组数据的第一行输入两个正整数N,M(<1=N,M<=100000),接下来一行,包含N个正整数,代表 Zeus 的获得的集合,之后M行,每行一个正整数S,代表 Prometheus 询问的正整数。所有正整数均不超过2^32。
输入的第一行是一个整数T(T < 10),表示共有T组数据。
每组数据的第一行输入两个正整数N,M(<1=N,M<=100000),接下来一行,包含N个正整数,代表 Zeus 的获得的集合,之后M行,每行一个正整数S,代表 Prometheus 询问的正整数。所有正整数均不超过2^32。
Output
对于每组数据,首先需要输出单独一行”Case #?:”,其中问号处应填入当前的数据组数,组数从1开始计算。
对于每个询问,输出一个正整数K,使得K与S异或值最大。
对于每个询问,输出一个正整数K,使得K与S异或值最大。
Sample Input
2 3 2 3 4 5 1 5 4 1 4 6 5 6 3
Sample Output
Case #1: 4 3 Case #2: 4
题目大意:
给出n个不超过2^32的正整数,接下来有m次询问,每次输入一个正整数s,输出这n个数中的某个整数k,使得s^k的值最大。解题思路:
根据异或的性质(相同得0,不同得1),如果要使得异或的值最大,那么s与k转化为二进制后要有尽量多的高位不同。这里用到了贪心的思想,我们优先考虑高位,使得高位相反,其次再考虑低位,这样才能使得异或的值最大。同时题目给出的内存比较大,然后就可以用trie树了。我们要建一个32层的二叉树,每一层的节点的两个子节点分别表示0和1,每次查询从高到低依次走相反的路径。
参考代码:
#include<map>
#include<stack>
#include<queue>
#include<cmath>
#include<vector>
#include<cctype>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const double eps=1e-10;
const int INF=0x3f3f3f3f;
const int MAXN=5000+50;
typedef long long LL;
struct node
{
node* next[2];
node()
{
memset(next,0,sizeof(next));
}
}*root;
int n,m;
void trie_insert(node* start,int num)
{
node* now=start;
for(int i=0; i<32; i++)
{
int id=(num>>(31-i)&1);//从高位到低位依次取出
if(now->next[id]==NULL)
now->next[id]=new node();
now=now->next[id];
}
}
int trie_query(node* start,int num)
{
node* now=start;
int res=0;
for(int i=0; i<32; i++)
{
int id=(num>>(31-i)&1);//从高位到低位开始查询
if(now->next[1-id])//如果与该位相反的儿子存在,那么就选择相反的儿子作为下一个位置
{
res=res<<1|(1-id);
now=now->next[1-id];
}
else//如果与该位相反的分支不存在,那么就只能选择存在的儿子
{
res=res<<1|id;
now=now->next[id];
}
}
return res;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif // ONLINE_JUDGE
int tcase,f=0;
scanf("%d",&tcase);
while(tcase--)
{
int t;
root=new node();
scanf("%d%d",&n,&m);
for(int i=0; i<n; i++)
{
scanf("%d",&t);
trie_insert(root,t);
}
printf("Case #%d:\n",++f);
for(int i=0; i<m; i++)
{
scanf("%d",&t);
printf("%d\n",trie_query(root,t));
}
}
return 0;
}