zoukankan      html  css  js  c++  java
  • codeforces 165E Compatible Numbers

    昨天看到一道好题,现与大家分享一下。

    http://codeforces.com/contest/165/problem/E

    题目大意:给一个序列a1~an(n<=1000000),问对于每一个ai来说,是否存在一个数x使得 ai&x==0且x是序列a 中的元素。ai的范围是(1<=ai<=4000000)。

    思路:对于一个数,比如说53,其二进制表示为 110101,取它的反,即为001010,我们知道,若一个数x使得x&53==0,则x的二进制一定是这样一个形式:00?0?0(其中?表示可以为0也可以为1)。那么我们设这样一个数组 vis[x]={0,1},表示x是否可以由序列a中的元素,将其二进制中的若干0改为1后得到。比如说如果a中存在53(110101),那么我们可以得到 (111101)61,(110111)55,(111111)63,则vis[53]=vis[55]=vis[61]=vis[63]=1,这个数列我们可以先预处理一遍得到,因为ai最大为4000000,所以预处理的复杂度为 (1<<K)*K(其中K为序列中最大的数其二进制表示的长度,最大为22)。那么有了这个数组,我们就可以求出对于每一个数的答案了,首先,我们要求ai对应的数,我们首先取反,得到tmp,此时若vis[tmp]==0,我们可以肯定序列a中不存在与ai与操作后等于0的数,直接输出-1,否则,我们可以知道一定存在一个数,那么我们怎么求这个数呢?

    具体步骤如下:

    我们首先设答案ans为0,我们枚举tmp的每一位,如果遇到1,则我们把这一位设为0后,再看tmp是否存在,如果不存在,说明我们要找的那个数这一位上一定为1,则我们将ans的这一位赋值为1,然后将tmp恢复后继续遍历,如果存在,说明我们要找的数这一位可以为0(注意不是一定),则我们继续遍历即可。如果遇到0,直接继续遍历,因为我们要找的数这一位上一定为0。遍历完之后,ans的值即为答案,输出即可。这一步的时间复杂度为O(n*K),(K由上面定义),可以在规定的时间内跑完。具体代码如下:

    #include <iostream>
    #include <string.h>
    #include <stdio.h>
    #include <algorithm>
    #define ll long long
    #define maxn 4500000
    using namespace std;
    int getlen(int x)
    {
        int sum=0;
        while(x)
        {
            sum++;
            x/=2;
        }
        return sum;
    }
    int vis[maxn];
    int a[1000010];
    int main()
    {
        //freopen("dd.txt","r",stdin);
        memset(vis,0,sizeof(vis));
        int n,max=0,i,j;
        scanf("%d",&n);
        for(i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            if(max<a[i])
            max=a[i];
            vis[a[i]]=1;
        }
        if(n==1)
       {
           printf("-1\n");
           return 0;
       }
    
        int len=getlen(max);
        int limit=(1<<len)-1;
        for(i=0;i<=limit;i++)
        {
            if(!vis[i])
            continue;
            for(j=0;j<len;j++)
            {
                if(((1<<j)&i)==0)
                {
                    vis[i^(1<<j)]=1;
                }
            }
        }
        for(i=1;i<=n;i++)
        {
            int tmp=limit-a[i];
            //printf("%d\n",tmp);
            if(!vis[tmp])
            printf("-1 ");
            else
            {
                int ans=0;
                for(j=0;j<len;j++)
                {
                    if(tmp&(1<<j))
                    {
                        if(vis[tmp^(1<<j)])
                        tmp^=(1<<j);
                        else
                        {
                            ans+=1<<j;
                        }
                    }
                }
                printf("%d ",ans);
            }
        }
        printf("\n");
        return 0;
    }


     

  • 相关阅读:
    Python使用Django创建第一个项目
    如何使用RobotFramework编写好的测试用例
    接口测试 总结(什么是接口测试)
    APP接口测试
    Django基础五之中间件
    Django基础五之django模型层(二)多表操作
    Django基础五之django模型层(一)单表操作
    Django基础四之模板系统
    Django基础三之视图函数
    DJANGO2--url路由
  • 原文地址:https://www.cnblogs.com/xinyuyuanm/p/3000809.html
Copyright © 2011-2022 走看看