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 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
题意分析:题意就是在给定的几个数中,问有多少个任意两个数的异或比这两个数都要大
思路:想要使一个数异或之后变大,找到这个数的二进制为0的位置,然后看有多少数二进制第一位也在相同位置,有多少个就有多少数可以让他变大
一个数的二进制第一位数肯定是1,也就是我们要记录的位置。
在这我先解释一下右移运算和按位与运算,首先是右移运算,右移就是对于一个二进制数整体向右移动,高位补零,低位舍去,举个例子例如13这个数对应的二进制数就是1101,右移一位就是110,在右移一位是11,在右移一位为1,在右移一位就变为0,上面对应的都是二进制数; 按位与操作 0&0=0; 0&1=0; 1&0=0; 1&1=1
例子:10&9: 0000 1010 & 0000 1001 = 0000 1000 = 8
AC代码如下:

#include<stdio.h>
#include<string.h>
int book[101000],a[101000];
int main()
{
	int T,i,n,sum,x,sum1;
	scanf("%d",&T);
	while(T--)
	{
		memset(book,0,sizeof(book));//book数组是用来记录每个数对应二进制数的位数
		scanf("%d",&n);
		sum=0;
		for(i=1;i<=n;i++)
		{
			sum1=0;
			scanf("%d",&a[i]);
			x=a[i];
			while(x)
			{
				sum1++;
				x>>=1;
			}
			book[sum1]++;//找到每个数对应二进制最高位的位置,记录出现的次数
		}
		for(i=1;i<=n;i++)
		{
			x=a[i];sum1=0;
			while(x)
			{
				sum1++;
				 if(!(x&1))//当找到二进制数为零的位置时就把在这个位置为1的数个数加起来
					sum+=book[sum1];
				x>>=1;
			}
		}
		printf("%d\n",sum);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44313771/article/details/104542521