zoukankan      html  css  js  c++  java
  • ZOJ 4057 XOR Clique(位运算)

    XOR Clique


    BaoBao has a sequence a​1​,a​2,...,a​n. He would like to find a subset S of {1,2,...,n} such that ∀i,j∈S, a​i ⊕a​j<min(ai ,aj) and ∣S∣ is maximum, where ⊕ means bitwise exclusive or.

    Input
    There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:

    The first line contains an integer n (1≤n≤100000), indicating the length of the sequence.

    The second line contains n integers: a​1​​ ,a​​2​ ,...,a​n(1≤ai≤10的9次方), indicating the sequence.
    It is guaranteed that the sum of n in all cases does not exceed 100000.

    Output
    For each test case, output an integer denoting the maximum size of S.

    Sample Input
    3
    3
    1 2 3
    3
    1 1 1
    5
    1 2323 534 534 5

    Sample Output
    2
    3
    2


    题意,求在a数组中找出s子集,要求子集中任意两个数异或之后比这两个数都小,求最大子集里面元素的个数;
    可以知道,2进制的0和1异或才是1,其他是0,要求两个数异或要更小,则必须两个相同长度的数二进制的最高位要都是1,所以,只需要知道在每个长度的集合中,存在多少个元素,元素最多的那个就是答案;

    例3中,对应的log2(x)为0,11,9,9,2,可以得到534和534在长度9的子集中,最大子集元素个数为2;

    #include<iostream>
    #include<algorithm>
    #include<string.h>
    #include<cmath>
    #include<map>
    using namespace std;
    map<int,int>m;//记录符合条件的子集元素个数
    int main()
    {
             //init();
             int T;
             scanf("%d",&T);
             while(T--)
             {
                      m.clear();
                      int n,x;
                      scanf("%d",&n);
                      while(n--){
                               scanf("%d",&x);
                               m[log2(x)]++;//求二进制位数并记录出现次数
                      }
                      int cnt=0;
                      map<int,int>::iterator it;
                      for(it=m.begin();it!=m.end();it++)
                               cnt=max(cnt,it->second);//求m中最大值
                      printf("%d
    ",cnt);
             }
             return 0;
    }
    /*
    log2(x)求法
    int w[31];
    void init(){
             for(int i=0;i<30;i++)
                      w[i]=1<<i;
    }
    int find(int x)
    {
             int l=0,r=30;
             while(r-l>1)
             {
                      int mid=l+r>>1;
                      if(w[mid]<=x)
                               l=mid;
                      else   r=mid;
             }
             if(w[r]<x)
                      return r;
             else
                      return l;
    }*/
    
  • 相关阅读:
    Ubuntu 16 安装redis客户端
    crontab 参数详解
    PHP模拟登录发送闪存
    Nginx配置端口访问的网站
    Linux 增加对外开放的端口
    Linux 实用指令之查看端口开启情况
    无敌的极路由
    不同的域名可以指向同一个项目
    MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error
    Redis 创建多个端口
  • 原文地址:https://www.cnblogs.com/aeipyuan/p/9893109.html
Copyright © 2011-2022 走看看