【ZOJ3870】Team Formation(异或+思维)

题目链接

Team Formation


Time Limit: 2 Seconds      Memory Limit: 131072 KB


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 109.

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个数,如果满足a^b > MAX(a, b),就算一种组合,问n个数之间这样的组合有多少个。

【解题思路】

将n个数存入数组中从小到大排序,如果要让一个数增大,只要该数化为二进制后的出现0的位置跟1异或就会变大,同时需要满足另一个数的最高位为该数出现0位置的位数即可。

比如1010,从右往左数第0位为0,ans+最高位是0位且为1的数的个数,因为最高位在0位且是1那前面几位肯定都是0,异或后肯定变大了,此处这个数只可能是0001,当第2位时也为0,那么同理必须加上01XX这样的数,异或后肯定变大了。

【代码】

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int a[maxn],cnt[maxn],b[maxn];//cnt[i]代表a数组都转换成二进制数后最高位所在位置i为1的数的个数;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,ans=0;
        memset(a,0,sizeof(a));
        memset(cnt,0,sizeof(cnt));
        scanf("%d",&n);
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        sort(a,a+n);
        for(int i=0;i<n;i++)
        {
            int x=a[i],num=0;
            while(x)
            {
                int t=x%2;
                b[num++]=t;
                x/=2;
            }
            for(int j=0;j<num;j++)
            {
                if(b[j]==0)
                    ans+=cnt[j];//当某一位为0时,因为已经排序,所以之前该位置最高位为1的数的前面肯定都是0
            }
            cnt[num-1]++;//最高位是1的位置的个数++
        }
        printf("%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39826163/article/details/81950215