[模拟赛]异或最大值 maxinum

此题在考试时用暴力,暴了30分。

献上30分代码:

#include<stdio.h>
int a[100005];
int main()
{
    int n,t,c,i,max,j,d;
    freopen("maximum.in","r",stdin);
    freopen("maximum.out","w",stdout);
    scanf("%d",&t);
    while(t--)
    {
        max=0;
        scanf("%d%d",&n,&c);
        for(i=1;i<=n;i++)
            scanf("%d",&a[i]);
        if(c==1)
        {
            for(i=1;i<=n;i++)
                for(j=i+1;j<=n;j++)
                {
                    d=a[i]&a[j];
                     if(d>=max)max=d;
                }
        }
        if(c==2)
        {
            for(i=1;i<=n;i++)
                for(j=i+1;j<=n;j++)
                {
                    d=a[i]^a[j];
                     if(d>=max)max=d;
                }
        }
        if(c==3)
        {
            for(i=1;i<=n;i++)
                for(j=i+1;j<=n;j++)
                {
                    d=a[i]|a[j];
                     if(d>=max)max=d;
                }
        }
        printf("%d\n",max);
    }
    fclose(stdin);
    fclose(stdout);
    return 0;
} 
View Code

 

注意与运算符(&),或运算符(|),异或运算符(^)

详细解说:http://www.cnblogs.com/wisdom-jie/p/7732940.html

正解

1、0-1字典树: 
这里其实是就是二叉树,之所以叫做字典树是因为我们的算法把一个数当成了一个31位的字符串来看,比如1就是三十个零外加一个一,这一部分还是比较简单的。 
2、贪心找最大异或值: 
异或运算有一个性质,就是对应位不一样为1,我们要让结果最大化,就要让越高的位置为1。我们找跟一个数的异或结果最大的数,就从树的根结点(最高位)开始找,如果对应位置这个数是0,优先去找那一位为1的数,找不到才去找0;如果对应位置这个数是1,优先去找那一位为0的数,找不到才去找0;最终找到的数就是跟这个数异或结果最大的数。n个数,每个数找一个这样的数并算出结果求其中的最大值,可以得到答案。

参考代码如下:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n,a[100005],tmp[35];
struct node
{
    int val;
    node *left, *right;
    node(int value=-1)
    {
        val = value;
        left = right = NULL;
    }
};
node *head = NULL;
void cal(int num)
{
    memset(tmp,0,sizeof(tmp));
    int cnt=0;
    while(num)
    {
        tmp[cnt++]=num%2;
        num/=2;
    }
    for(int i=0;i<15;i++)
        swap(tmp[i],tmp[30-i]);
}
void insert(node* &head, int index, int &num)
{
    if(index+1==31)
    {
        head->val = num;
        return;
    }
    if(tmp[index+1]==0 && !head->left)
        head->left = new node(-1);
    if(tmp[index+1]==1 && !head->right)
        head->right = new node(-1);
    if(tmp[index+1]==0)
        insert(head->left,index+1,num);
    if(tmp[index+1]==1)
        insert(head->right,index+1,num);
}
int dfs(node* &head,int index)
{
    if(index+1==31)
        return head->val;
    if(tmp[index+1]==0)
    {
        if(head->right)
        {
            return dfs(head->right,index+1);
        }
        else
        {
            return dfs(head->left,index+1);
        }
    }
    else
    {
        if(head->left)
        {
            return dfs(head->left,index+1);
        }
        else
        {
            return dfs(head->right,index+1);
        }
    }
}
int main()
{
    while(scanf("%d",&n))
    {
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        head = new node(-1);
        for(int i=0;i<n;i++)
        {
            cal(a[i]);
            insert(head,-1,a[i]);
        }
        int ans=0;
        for(int i=0;i<n;i++)
        {
            cal(a[i]);
            ans = max(ans, a[i]^dfs(head,-1));
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

posted @ 2017-10-25 23:15  wisdom_jie  阅读(1060)  评论(0编辑  收藏  举报