2014百度之星資格賽第三題

Xor Sum
Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others)
Total Submission(s): 4445    Accepted Submission(s): 652
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

       這道題最常規的解法就是簡單的循環,一個個的比較判斷那個數的異或最大,時間複雜度爲0(TNM),在OJ平臺上肯定是時間會超時的。

       因此,應該採用其他的方法,減少計算的次數,降低時間複雜度。首先要知道的是什麼情況下,給定一個數a,如何在一組數據中找到其異或的最大值。一般我們現將數首先取反。在該組數據中與已知的異或最大的數的特點就是從該數二進制的最高開始匹配,儘可能與~a的二進制相同。

       基於此,第一種解法就是使用二叉樹,左邊表示0,右邊表示1。所以該樹的深度最多爲32。在匹配的時候從樹開始,往下匹配,到葉子節點時,就是其最大的異或數。該算法的缺點就是要構建二叉樹,浪費了一點時間(可以自己去算一算)。但是匹配的時候大大減少了時間。

      第二種解法就是現將一組數進行排序,然後採用二分查找的方式去查找數據,缺點就是要排序。2種算法都是常見的減少時間複雜度的經典算法。

代碼如下:

/*#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<fstream>
using namespace std;
#define MAXSIZE 100000
typedef bool bits;
typedef struct bitTree
{
    bits data;
    bitTree *left,*right;
    //bitTree(bits _data=0):data(_data),left(NULL),right(NULL){}
}bitTree;
unsigned int a[MAXSIZE];
unsigned int b[MAXSIZE];
int length,question;

void create(bitTree *root,unsigned int temp)
{
    int i=1,j=32;
    bitTree *q=root;
    bitTree *child;
    bits middle_bits;
    while(i<=j)
    {
        middle_bits=temp>>31;
        if(middle_bits==0)
        {
            if(q->left==NULL)
            {
                child=(struct bitTree *)malloc(sizeof(struct bitTree)) ;
                child->data=0;
                child->left=child->right=NULL;
                q->left=child;
            }
            q=q->left;
        }
        else
        {
            if(q->right==NULL)
            {
                child=(struct bitTree *)malloc(sizeof(struct bitTree)) ;
                child->data=1;
                child->left=child->right=NULL;
                q->right=child;
            }
            q=q->right;
        }
        temp=temp<<1;
        i++;
    }
}

ofstream ofs("d.txt");
void fun(bitTree *root)
{
    bitTree* ttemp=root;

    unsigned int result;
    bits middle_bits;
    int i,j=1,k=32;
    for(i=0;i<question;i++)
    {
        result=0;
        ttemp=root;
        j=1;
        unsigned int temp=~b[i];
        while(j<=k)
        {
            middle_bits=temp>>31;
            if(middle_bits==0)
            {
                if(ttemp->left!=NULL)
                {
                    result=result<<1;
                    ttemp=ttemp->left;
                }
                else
                {
                    result=(result<<1)+1;
                    ttemp=ttemp->right;
                }
            }
            else
            {
                if(ttemp->right!=NULL)
                {
                    result=(result<<1)+1;
                    ttemp=ttemp->right;
                }
                else
                {
                    result=result<<1;
                    ttemp=ttemp->left;
                }
            }
            j++;
            temp=temp<<1;
        }
      // printf("%u\n",result);
       ofs<<result<<"  ";
    }
    ofs<<endl;

}

int main()
{
    //ifstream ifs("a.txt");
    //cin.rdbuf(ifs.rdbuf());
    freopen("a.txt","r",stdin);
    int number;
    scanf("%d",&number);
    bitTree *root;

    int i,k=1;
    while(k<=number)
    {
        scanf("%d%d",&length,&question);
        for(i=0;i<length;i++)
            scanf("%u",&a[i]);
        for(i=0;i<question;i++)
            scanf("%u",&b[i]);
        root=(struct bitTree *)malloc(sizeof(struct bitTree)) ;
        root->data=1;
        root->left=root->right=NULL;
        for(i=0;i<length;i++)
            create(root,a[i]);
        printf("Case #%d:\n",k);
        fun(root);
        k++;
    }
}*/


第二種解法:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<fstream>
using namespace std;
const int maxn=100000+5;
const int inf=1<<31;
unsigned int s[maxn];
int main(){
    freopen("d.txt","r",stdin);
    ofstream  fs( "e.txt");
    int kase;
    cin>>kase;
    for(int run=1;run<=kase;run++){
        printf("Case #%d:\n",run);
        int n,m;
        cin>>n>>m;
        for(int i=0;i<n;i++)
            scanf("%d",&s[i]);
        sort(s,s+n);
        while(m--){
            unsigned int x;
            scanf("%d",&x);
            x=~x;
            int L=0,R=n-1;
            unsigned int bit=inf;
            while(bit){
                if(L==R) break;
                unsigned int y=bit&x;
                if(y){
                    int l=L,r=R,mid,ans=-1;
                    while(l<=r){
                        mid=(l+r)/2;
                        if(s[mid]&bit){
                            ans=mid;
                            r=mid-1;
                        }
                        else
                            l=mid+1;
                    }
                    if(ans!=-1)
                        L=ans;
                }
                else{
                    int l=L,r=R,mid,ans=-1;
                    while(l<=r){
                        mid=(l+r)/2;
                        if((s[mid]&bit)==0){
                            ans=mid;
                            l=mid+1;
                        }
                        else
                            r=mid-1;
                    }
                    if(ans!=-1)
                        R=ans;
                }
                bit=bit>>1;
            }
       // printf("%u\n",s[L]);
        fs<<s[L]<<" ";
        }
        fs<<endl;
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章