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 1e9.
Output
For each case, print the answer in one line.
Sample Input
2 3 1 2 3 5 1 2 3 4 5Sample Output
1 6
【题意】求出n个数字里满足 x^y>max(x,y) 的个数
【分析】对于某个数字,先转换成二进制,比如
1 0 0 0 1 0 1
若要使该数变大,则把0变成1,并且该0位前面所有位的1都不能变
那么,假设 x 的第 i 位是0(前提是第 i 位不是 x 的最高位),那么如果使 x 与 y 异或并且结果变大,则第 i 位是 y 的最高位,并且该位是1,这样异或的结果必然变大;
所以 bit[] 数组统计每一位作为最高位的数的个数;
然后是与运算;要找出最高位的 1,可以用 x 与 (1<<now)进行与运算,如果结果是1,则找到最高位;(因为与100000...(若干个)进行与运算时,只有当1与运算的那位是1答案才为1,否则全0)
最后统计答案时,仍旧是与运算,找该位是0的位,加上该位作为最高位的数字的个数;
因为题上范围说是不超过1e9,所以数字都是在int范围内的,那么最多就是32位。而进行位运算找最高位的1或者低位的0时,now初值赋值为31即可实现从高位往低位找从而找到最高位的1;
【代码】
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int a[maxn];
int bit[100];
void init(int x)
{
int now=31;
while(now>=0)
{
if(x&(1<<now))
{
bit[now]++;
break;
}
now--;
}
}
int main()
{
int t;scanf("%d",&t);
while(t--)
{
memset(bit,0,sizeof(bit));
int n;scanf("%d",&n);
for(int i=0;i<n;++i)
{
scanf("%d",&a[i]);
init(a[i]);
}
long long ans=0;
for(int i=0;i<n;++i)
{
int now=31;
while(now>=0)
{
if(a[i]&(1<<now))
break;
now--;
}
while(now>=0)
{
if(!(a[i]&(1<<now)))
ans+=bit[now];
now--;
}
}
printf("%lld\n",ans);
}
return 0;
}