您的位置:首页 > 其它

ZOJ 3870 Team Formation(浙江省第12届ACM省赛第二题)

2015-04-26 14:05 417 查看
For an upcoming programming contest, Edward, the headmaster of Marjar University, is forming a two-man team fromN students of his university.

Edward knows the skill level of each student. He has found that if two students with skill levelA 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 containsN positive integers separated by spaces. The
ith integer denotes the skill level ofith 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
题意:t组数据,给n个数,计算n个数里有多少对A、B,使得A异或B大于max(A,B)

思路:一个数x的二进制表示中最高位是a,存在使得x异或y大于max(x,y)的y,假设此y转化为二进制最高位比a大(一样大x异或y大于max(x,y)必不成立),此y的二进制第a位必定为0.(因为为1必比y小)

 

我把每个数都进行处理。g[i]表示第i位是最高位的数的个数,,d[i]表示第i位不是最高位的数的个数。

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<stdlib.h>
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<queue>
using namespace std;
int g[66],d[66];
int main(){
//freopen("G://test.txt","r",stdin);
int t,n,fin,maxn;
scanf("%d",&t);
while(t--){
memset(g,0,sizeof(g));
memset(d,0,sizeof(d));
maxn=-1;
scanf("%d",&n);
for(int i=0;i<n;++i){
int temp;
scanf("%d",&temp);
int cc=1;
while(temp){
if(temp%2==1){
d[cc]++;
fin=cc;//记录最高位在哪一位
}
temp>>=1;
cc++;
}
g[fin]++;//记录最高位的个数
d[fin]--;//减去多加的最高位
if(fin>maxn)
maxn=fin;//记录所有数的最高位
}
int sum=0,ans=0;
for(int i=1;i<=maxn;++i){
sum+=g[i];//记录二进制最高位位数比i小和等于的
ans+=(n-sum-d[i])*g[i];//n-sum即二进制最高位位数比i大的数
}//n-sum-d[i]即二进制最高位位数比i大的数中第i位为0的个数
printf("%d\n",ans);
}

return 0;
}


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: