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); } }
相關文章
相關標籤/搜索