ZOJ-3870-Team Formation

原题
For an upcoming programming contest, Edward, the headmaster of Marjar University, is forming a two-man team from N students of his university.

Edward knows the skill level of each student. He has found that if two students with skill level A and B form a team, the skill level of the team will be A ⊕ B, where ⊕ means bitwise exclusive or. A team will play well if and only if the skill level of the team is greater than the skill level of each team member (i.e. A ⊕ B > max{A, B}).

Edward wants to form a team that will play well in the contest. Please tell him the possible number of such teams. Two teams are considered different if there is at least one different team member.

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 (2 <= N <= 100000), which indicates the number of student. The next line contains N positive integers separated by spaces. The ith integer denotes the skill level of ith student. Every integer will not exceed 10^9.

Output
For each case, print the answer in one line.

Sample Input
2
3
1 2 3
5
1 2 3 4 5
Sample Output
1
6
题意:
有n个选手,每一个选手都有自己的key值(题目中的技术水平),当两个选手的key值的异或值大于两个人的key时称其为出色队伍,现在要求从中找出能组合成出色队伍的最大数量。(一个人可以分别与多个人组合成出色队伍)
题解:
这道题,一开始是想枚举但是肯定是TLE了。之后想了想怎么样才能够满足题意呢?
先解释一下异或:相同为0,不同为1。那么怎样才能使异或值大于原先的key值呢?对于每一个人来说,是1的最高位肯定是不能变化的,所以我们要找到比他key值小的人,并且满足在第一个人的二进制中是0的位置时恰好是另一个人的1的最高位,这样就能够找出所有满足条件的队伍了?(更多细节见代码)
附上AC代码:

#include <iostream>
#include <cstring>
using namespace std;
int t,n,a[100005],bit[32];
void findbit(int x)//寻找每一个人1的最高位
{
    int l=31;//最大值是10^9,所以l取到31就行了
    while(l>=0)
    {
        if(x&(1<<l))//每次左移L位找与他相与为1的位置就是1的最高位
        {
            bit[l]++;//记录下1的最高位是L的人的个数
            return ;
        }
        l--;
    }
}
int main()
{
    cin>>t;
    while(t--)
    {
        long long cnt=0;//想一想组合的个数有多少个就知道为什么用long long了
        memset(bit,0,sizeof(bit));//每次初始化,否则一定WA
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
            findbit(a[i]);//寻找1的最高位
        }
        for(int i=1;i<=n;i++)
        {
            int l=31;
            while(l>=0)
            {
                if(a[i]&(1<<l))break;//找到了最高位的位置
                l--;
            }
            while(l>=0)
            {
                if(!(a[i]&(1<<l)))//找比他小的,并且在他二进制是0的位置恰好是另一个数1的最高位的情况
                {
                    cnt+=bit[l];//组合数相加
                }
                l--;
            }
        }
        cout<<cnt<<endl;
    }
    return 0;
}

欢迎评论!

猜你喜欢

转载自blog.csdn.net/wjl_zyl_1314/article/details/83211992