您的位置:首页 > 其它

HDU 4825 Xor Sum

2016-06-22 08:13 423 查看
http://acm.hdu.edu.cn/showproblem.php?pid=4825

字典树的经典问题—->求异或最大值

题意大概是这样的,给你n个数让你存起来,之后每一次输入一个数num。(执行m次)

把num的值和之前的n个数的进行异或,要求输出能使其异或后数值最大的那个数字。

因为最大不超过32位,所以我先把输入的n个数字转换为字符串,变为34位,用0补位。

之后每次输入的时候也把num转换为字符串,之后取反,之后取值就行了。

#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
using namespace std;
typedef struct Trie_Node
{
struct Trie_Node *nexts[2];
}TrieNode,*Trie;

TrieNode *Creat_node()
{
Trie node=new TrieNode;
memset(node->nexts,0,sizeof(node->nexts));
return node;
}

void convert_str(char *s,__int64 num)
{
int len=34,id;
s[len]='\0';
while(num)
{
s[--len]=(num&1)+'0';
num>>=1;
}
for(int i=len-1;i>=0;i--)
s[i]='0';
//printf("%s\n",s);
}

void InsertNode(char *s,Trie root)
{
Trie p=root;
int id;
for(int i=0;i<34;i++)
{
id=s[i]-'0';
if(root->nexts[id]==NULL)
root->nexts[id]=Creat_node();

root=root->nexts[id];
}
}

__int64 SearchNum(Trie root,char *s)
{
Trie p=root;
__int64 k=2,sum=0;
k<<=32;//先从最大的那位加和从最小的那么一起加没有什么区别。
int id;
for(int i=0;i<34;i++)
{
id=s[i]-'0';

if(p->nexts[id]==NULL)
p=p->nexts[id^1];     //这里,因为传入的是取反后的二进制,所以不相同是即原数的二进制的这一位与之前存入的位数的二进制相同所以为0
else
{
p=p->nexts[id];//    相同后 ,加K的值
sum+=k;
}
k>>=1;     //k每次都除以2
}
return sum;
}

int main()
{
int t,n,m;
scanf("%d",&t);
char str[50];
while(t--)
{
Trie root=Creat_node();
scanf("%d %d",&n,&m);
__int64 num;
while(n--)
{
scanf("%I64d",&num);
convert_str(str,num);
InsertNode(str,root);
}
static int times=1;
printf("Case #%d:\n",times++);
__int64 temp;
while(m--)
{
scanf("%I64d",&num);
convert_str(str,num);
for(int i=0;i<34;i++)
{
if(str[i]=='1')
str[i]='0';
else str[i]='1';
}
printf("%I64d\n",SearchNum(root,str)^num);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息