FJUT ACM 2160 Xor Sum

Xor Sum

TimeLimit:1000MS  MemoryLimit:132768KB
64-bit integer IO format: %I64d
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异或值最大。
SampleInput
2
3 2
3 4 5
1
5
4 1
4 6 5 6
3
SampleOutput
Case #1:
4
3
Case #2:
4
【思路】:看见题目第一直觉就是直接异或,而后比较就能够ac,固然结果是一个TLE,由于询问次数跟次数都太大了,
O(N^2)的复杂度是一定超时的,其实这题是能够用字典树进行优化的,由于要找到异或的最大值,咱们彻底能够讲输入的
值建成一颗0,1字典树,而输入每一个值要异或最大,就必须选择匹配度较高的二进制树,一开始我是从低位向高位搜索,结果
发现案例过不了,由于咱们能够获得2^2>∑(2^0*1+2^1*1);因此说只要一个高位的是1,就算是低位全是1也比他来得小
那咱们就必须从高位向低位进行查找,可是有个问题没法解决,就是不少个数的二进制数的位长不同,因此我观察了题目的数据
最大不会超过2^33,因此我就开了一个35的数组来储存一个数的全部位数,而后不够的所有补0,就能够等长来建字典树,而后输入
取反的过程要注意为0的高位都得变成1;而后再去匹配,匹配的时候顺带计算,就能够得出结果,一开始我用这个思路又TLE了一发,
后来CWL学长发现我再计算数值时用了pow(),太慢,修改以后就ac了,emmmmmmm
真的死在pow();
贴上代码:(01字典树)
#include<stdio.h> #include<string.h> #include<stdlib.h> typedef long long ll; typedef struct node { int n; struct node *next[2]; } tire; tire *creattire() { tire *q; q=(tire *)malloc(sizeof(tire)); q->n=0; for(int i=0; i<2; i++) { q->next[i]=NULL; } return q; } void addtire(int word[],tire *root,int n) { for(int i=0; i<=n; i++) { int ans=word[i]; if(root->next[ans]==NULL) { tire *q; q=creattire(); root->next[ans]=q; root=root->next[ans]; } else root=root->next[ans]; } } void deletetire(tire *root) { if(root==NULL) return ; for(int i=0; i<2; i++) { if(root->next[i]!=NULL) { deletetire(root->next[i]); } } free(root); } ll remath(int word[],tire *root,int n) { int team[40]; int j=0; for(int i=0; i<=n; i++) { if(root->next[word[i]]!=NULL) { team[j++]=word[i]; root=root->next[word[i]]; } else { if(word[i]==0) { team[j++]=1; root=root->next[1]; } else { team[j++]=0; root=root->next[0]; } } } ll sum=0; for(int i=n; i!=-1; i--) { sum+=team[i]*(1<<(n-i));///使用pow()TLE } return sum; } int word[40]; int main() { int t; tire *root; scanf("%d",&t); int y=0; while(t--) { printf("Case #%d:\n",++y); int n,k; scanf("%d%d",&n,&k); root=creattire(); for(int i=0; i<n; i++) { ll num; int j=35; scanf("%I64d",&num); memset(word,0,sizeof(word)); while(num!=0) { if(num&1) word[j--]=1; else word[j--]=0; num>>=1; } addtire(word,root,35); } for(int i=0; i<k; i++) { ll nums; scanf("%I64d",&nums); for(int i=0; i<40; i++) word[i]=1; int j=35; while(nums!=0) { if(nums&1) word[j--]=0; else word[j--]=1; nums>>=1; } nums=remath(word,root,35); printf("%I64d\n",nums); } deletetire(root); } }
相关文章
相关标签/搜索