异或与二进制

题目描述:

BaoBao has a sequence a1​,a2​,...,an. He would like to find a subset S of {1,2,...,n}such that i,jSaiaj​<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≤105), indicating the length of the sequence.

The second line contains n integers: a1​,a2​,...,an (1≤ai​≤109), indicating the sequence.

It is guaranteed that the sum of n in all cases does not exceed 105.

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

题目大意:

  给出一个序列a1,a2,a3.....,s中放的是子序列的下标,则在此子序列中存在i,j属于s,使得 ai异或aj小于min(ai,aj)并且s的长度最大。

思路:

  因为两个数异或(相同为0,不同为1)时,若两个数的二进制表示的长度相同,则它们异或后得到的数将会比这两个数都小,才会满足题目条件,而当两个数的二进制表示的长度不同时,异或得到的数将会比这两个数都大,不符合条件。所以本题就可以转化为求这个序列中最多有几个数的二进制位数相同,这个最多的数即是最大的序列长度。

代码:

​
#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<map>
using namespace std;
int a[100001],b[100001];
map<int,int>m;
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
	    m.clear();
		int n;
		scanf("%d",&n);
		for(int i=0;i<n;i++)
			scanf("%d",&a[i]);
        for(int i=0;i<n;i++)
        {
            int count=0;
            while(a[i]>0)
            {
                count++;
                a[i]>>=1;   //记录每个数的二进制表示的位数
            }
            b[i]=count;
            m[b[i]]++;       //将有相同位数的数的个数保存在map中
        }      
        map<int,int>::iterator i;
        int mmax=-1;
        for(i=m.begin();i!=m.end();i++)
        {
            if((i->second)>mmax)    //遍历map找出最大的相同个数是几,即是要求的最大序列的长度
                mmax=i->second;
        }
        printf("%d\n",mmax);
	}
	return 0;
}

​

猜你喜欢

转载自blog.csdn.net/Krismile_/article/details/82860214