• 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:
    ",++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
    ",nums);
            }
            deletetire(root);
        }
    }
  • 相关阅读:
    PHP array_udiff_assoc() 函数
    PHP array_udiff() 函数
    app已损坏,打不开。你应该将它移到废纸篓
    [WC2013]糖果公园
    win10 uwp 绑定静态属性
    win10 uwp 修改Pivot Header 颜色
    win10 uwp 修改Pivot Header 颜色
    win10 uwp 修改Pivot Header 颜色
    win10 uwp 反射
    win10 uwp 反射
  • 原文地址:https://www.cnblogs.com/qq136155330/p/8580672.html
Copyright © 2020-2023  润新知