您的位置:首页 > 其它

百度之星 1003 Xor Sum

2014-05-18 20:17 183 查看
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。

Output

对于每组数据,首先需要输出单独一行”Case #?:”,其中问号处应填入当前的数据组数,组数从1开始计算。

对于每个询问,输出一个正整数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

本来想用int卡过去的,但是实践证明,不行。runtime error(系统提示爆栈)了好多次。

后来改成了__int64 就是开始wa了。期间也改了记录数值的方式,但依然是错的。这个题真不知道改怎么做了。

有没有路过的好心人帮忙纠正一下错误的?

首先,先贴一发 runtime error的代码

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <stack>
#include <vector>
#include <queue>
#include <algorithm>
#include <iostream>
using namespace std;
struct node
{
int data;//data记录那个具体的数字
node *num0;
node *num1;
};
void build(int a[],node *head,int leave,int num)//建树
{
if(leave<0)return ;
if(a[leave]==1)
{
if(head->num1==NULL)
{
node *tem=new node();
head->num1=tem;
tem->num0=NULL;
tem->num1=NULL;
if(leave==0)
{
tem->data=num;
}
else build(a,tem,leave-1,num);
}
else build(a,head->num1,leave-1,num);
}
else
{
if(head->num0==NULL)
{
node *tem=new node();
head->num0=tem;
tem->num0=NULL;
tem->num1=NULL;
if(leave==0)
{
tem->data=num;
}
else build(a,tem,leave-1,num);
}
else build(a,head->num0,leave-1,num);
}
}
int query(int a[],int leave,node *head)//查询 如果询问的数在该位置为1为使异或值最大,则查询字典树里为0的值,相反亦然
{
if(leave<0)return head->data;
if(head->num0==NULL&&head->num1==NULL)return -1;
if(a[leave]==1)
{
if(head->num0!=NULL)return query(a,leave-1,head->num0);
return query(a,leave-1,head->num1);//如果字典树里没有0的值则往1处搜索
}
else if(a[leave]==0)
{
if(head->num1!=NULL)return query(a,leave-1,head->num1);
return query(a,leave-1,head->num0);
}
return -1;
}
int b[55];
void toBase(int num)//将一个数字转化为二进制
{
memset(b,0,sizeof(b));
int i=0;
while(num)
{
b[i++]=num&1;
num=num>>1;
}
}
void det(node *head)//内存释放,后来发现re不是这个错误T^T
{
if(head->num0!=NULL)det(head->num0);
if(head->num1!=NULL)det(head->num1);
free(head);
}
int main()
{
int T,n,m,i,j,k,x,y;
scanf("%d",&T);
for(int cs=1; cs<=T; cs++)
{
scanf("%d%d",&n,&m);
node *head=new node();
head->num0=head->num1=NULL;
for(i=0; i<n; i++)
{
scanf("%d",&x);
toBase(x);
build(b,head,33,x);
}
printf("Case #%d:\n",cs);
for(i=0; i<m; i++)
{
scanf("%d",&x);
toBase(x);
int ans=query(b,33,head);
printf("%d\n",ans);
}
// det(head);
}
return 0;
}


然后,再来贴一发wa的代码。其中记录方式也有改变

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <stack>
#include <vector>
#include <queue>
#include <algorithm>
#include <iostream>
using namespace std;
#define LL  __int64
struct node
{
int data;//data只保存0或者1的值,具体数值根据路径上的值读取
node *num0;
node *num1;
};
void build(int a[],node *head,int leave)
{
if(leave<0)return ;
if(a[leave]==1)
{
if(head->num1==NULL)
{
node *tem=new node();
head->num1=tem;
tem->num0=NULL;
tem->num1=NULL;
tem->data=1;
build(a,tem,leave-1);
}
else build(a,head->num1,leave-1);
}
else
{
if(head->num0==NULL)
{
node *tem=new node();
head->num0=tem;
tem->num0=NULL;
tem->num1=NULL;
tem->data=0;
build(a,tem,leave-1);
}
else build(a,head->num0,leave-1);
}
}
LL ans,tem;
void query(int a[],int leave,node *head)
{
ans+=(head->data)*tem;
tem/=2;
if(head->num0==NULL&&head->num1==NULL)return ;
if(a[leave]==1)
{
if(head->num0!=NULL)query(a,leave-1,head->num0);
else  query(a,leave-1,head->num1);
return ;
}
else if(a[leave]==0)
{
if(head->num1!=NULL) query(a,leave-1,head->num1);
else  query(a,leave-1,head->num0);
return ;
}
return ;
}
int b[55];
void toBase(LL num)
{
memset(b,0,sizeof(b));
int i=0;
while(num)
{
b[i++]=num%2;
num/=2;
}
}
void det(node *head)
{
if(head->num0!=NULL)det(head->num0);
if(head->num1!=NULL)det(head->num1);
free(head);
}
int main()
{
int T,n,m,i,j,k;
LL x,y;
y=1;
for(j=0; j<33; j++)
y*=2;
scanf("%d",&T);
for(int cs=1; cs<=T; cs++)
{
scanf("%d%d",&n,&m);
node *head=new node();
head->num0=head->num1=NULL;
head->data=0;
for(i=0; i<n; i++)
{
scanf("%I64d",&x);
toBase(x);
build(b,head,32);
}
printf("Case #%d:\n",cs);
for(i=0; i<m; i++)
{
scanf("%I64d",&x);
toBase(x);
ans=0;
tem=y;
query(b,32,head);
printf("%I64d\n",ans);
}
// det(head);
}
return 0;
}


求大神指明前进的方向。ORZ

此题已解决。以上两个代码可能是在十进制转换为二进制的并且以数组进行运算的时候出现了错误。32?31?33?没有弄对。当然,也只是可能罢了。

今天,换了一种方式,A掉了。此题get。代码贴之(字典树,数组模拟版):

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <stack>
#include <vector>
#include <queue>
#include <algorithm>
#include <iostream>
using namespace std;
#define LL __int64
#define MAX 3200000
struct node
{
LL data;
int num0,num1;
} nod[MAX];
LL num,tem;
void build(int index,LL a)
{
LL two=tem;
while(two>0)
{
if((a&two)!=0)
{
if(nod[index].num1==-1)
nod[index].num1=num++;
index=nod[index].num1;
}
else
{
if(nod[index].num0==-1)
nod[index].num0=num++;
index=nod[index].num0;
}
two=two>>1;
}
nod[index].data=a;
// cout<<index<<endl;
}
LL query(int index,LL a)
{
LL two=tem;
while(two>0)
{
if((a&two)==0)
{
if(nod[index].num1==-1)
index=nod[index].num0;
else index=nod[index].num1;
}
else
{
if(nod[index].num0==-1)
index=nod[index].num1;
else index=nod[index].num0;
}
two=two>>1;
}
// cout<<index<<"!"<<endl;
return nod[index].data;
}
void pre(int n)
{
tem=1;
for(int i=0; i<n; i++)
tem*=2;
}
void init(int n)
{
for(int i=0; i<n; i++)
{
nod[i].data=nod[i].num0=nod[i].num1=-1;
}
}
int main()
{
int T,n,m,i,j,k;
LL x;
pre(32);
scanf("%d",&T);
for(int cs=1; cs<=T; cs++)
{
init(MAX);
num=1;
scanf("%d%d",&n,&m);
for(i=0; i<n; i++)
{
scanf("%I64d",&x);
build(0,x);
}
printf("Case #%d:\n",cs);
for(i=0; i<m; i++)
{
scanf("%I64d",&x);
printf("%I64d\n",query(0,x));
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息