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 Tindicating 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 ithinteger 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
    1.首先异或运算,不同出1,相同出0;

    2.先把序列从小到大排列(原因待会说),开一个数组b用于记录每一位的数值(1或0),数组cnt用
于记录某个数最高位为1(即如果最高位是1就将该位的位数j作为cnt的下标,使cnt[j]++);在循环将b数
组赋值结束后,从低位往高位遍历,如果某一位是0的话,这个数跟之前走过的数并且该位为1的进行异或,
结果一定大于这两个数的最大值(因为从小到大排序,所以之前遍历的数肯定比当前的数小),这样,ans+=cnt[j],即 加上之前遍历过的该位为1的个数即为最终要求的答案。

    3.  第二组样例化为二进制分别为 1  10  11  100  101。可以发现,如果要让一个数增大,只要该
数化为二进制后的出现0的位置跟1异或就会变大,同时需要满足另一个数的最高位为该数出现0位置的位数,
如10可以跟1异或变为11 ,100可以跟10、11、1异或分别变为110,111,101,而101只能跟两位的进行异或,
因为它的0出现的位置为第二位,最后求和就行了。
#include<bits/stdc++.h>

using namespace std;
int a[100000],b[50],cnt[50];

int main()
{
	int t;
	scanf("%d",&t);
	while (t--)
	{
		int n,ans = 0;
		scanf("%d",&n);
		for (int i=0;i<n;i++)
			scanf("%d",&a[i]);
		sort(a,a+n);
		memset(cnt,0,sizeof(cnt));
		for (int i=0;i<n;i++)
		{
			int j = 0;
			while (a[i])
			{
				b[j++] = a[i] % 2;
				a[i] /= 2;
			}
			for (int k=0;k<j;k++)//表示首位是这个位置的并且为1的,0与之异或一定变大;
			{
				if (b[k]==0)
					ans += cnt[k];
			}
			cnt[j-1]++;//让该位置为1的个数加1;
		}
		printf("%d\n",ans);
	}
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/qq_40912854/article/details/89062051