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

    求补集。题意:给出一列长为n(n<=10^6)的数ai(0<=ai<=4*10^6)。对每个数ai,有一个询问:在这列数中是否存在一个数aj,是的ai&aj=0。

    对于一个数,比如说90(1011010),对每一位取反,得到37(0100101)。显然,37&90=0,如果数列中存在37的话,那么就找到了这样的一个数aj了,当然,如果存在(0100101)的补集,这个数字也是可以找到的,比如说36(0100100),有另外的7个数(就是把1变成0就是了)也是可以的。

    那么现在的问题转化为如何来求这些补集,显然,如果对于每一个集合如果直接枚举,假设这个集合里有k个1的话,则复杂度将达到o(n*2^k),这还不如直接暴力(n^2)来的快。。其实,对于一个暂时为空的集合,它完全有可能是一个非空集合的子集,从低位到高位对这个空集做与操作,这个与出来的数所对应的集合(设为A)如果非空的话,那么这个集合就是A集的子集了。4*10^6<(1<<22) 最多22位,这样做的复杂度就是o(22*10^6),可以接受。

     1 #include <cstdio>
     2 int a[1000010],vis[1<<22];
     3 int main(){
     4     int n,mask = (1<<22)-1;
     5     scanf("%d",&n);
     6     for(int i = 0;i < n;i++){
     7         scanf("%d",&a[i]);
     8         vis[mask^a[i]] = a[i];
     9     }
    10     for(int i = mask;i >= 0;i--){
    11         if(vis[i])  continue;
    12         for(int j = 0;j < 22;j++){
    13             if(vis[i|(1<<j)]){
    14                 vis[i] = vis[i|(1<<j)];
    15                 break;
    16             }
    17         }
    18     }
    19     for(int i = 0;i < n;i++){
    20         if(vis[a[i]])   printf("%d ",vis[a[i]]);
    21         else    printf("-1 ");
    22     }
    23 }
    View Code
  • 相关阅读:
    jQuery插件开发全解析(转)
    isMemberOfClass和isKindOfClass之间区别
    NSArray,NSSet,NSDictionary总结 (转)
    NSIndexPath(转)
    Maven在dos窗口中的命令
    JPA概要
    fedora的输入法
    iQQ 学习笔记2 :借助新浪微博输入验证码、远程控制退出
    使用EXCEL制作通用打印模块
    字符串加密解密方法
  • 原文地址:https://www.cnblogs.com/zhexipinnong/p/3434376.html
Copyright © 2011-2022 走看看