您的位置:首页 > 其它

ZOJ 3870 Team Formation 亦或运算

2017-04-24 18:23 435 查看
题目地址:点击打开链接

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

题意 :

给出一个数列,每次选出两个数,如果这两个数满足 a^b > max(a,b); 就是满足题意的方案,方案数+1.

如果用暴力,枚举所有的情况,复杂度O(n*(n-1)/2),最坏的情况n=十万,肯定超时。

思路:

转化成二进制来做。亦或就是不进位的加法。对于任意的二进制数a,找一个满足条件的二进制数b,

使a^b > max(a,b),

例如:

对于a = 1 0 0 1 0 1;  寻找符合条件的b,不妨我们只找比a小的b,那么max(a,b) = a   

我们只需关心a的0位,我们在他的0位上,亦或上1,则0^1=1;

比如

1 0 0 1 0 1

^ 1 0 0 0 0   得

1 1 0 1 0 1 =c 。c = a^b > a 符合题意.。所以我们只需在a的0位上亦或上1,只要让b的这一位是1,高位是0,低位随意。

那么,只需要统计有多少个这样的b,每一个a对应的b,数量加起来就是答案

代码:

#include<stdio.h>
#include<string.h>
int T,n;
int a[100100];
int count[33];//count[x]记录x长度的二进制数有几个
int lenth(int n)
{
int i=0;
while(n)
{
n/=2;
i++;
}
return i;
}
int main()
{
scanf("%d",&T);
while(T--)
{
memset(count,0,sizeof(count));
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
int x=lenth(a[i]);//计算a[i]的二进制长度
count[x]++;
}
long long sum=0;
for(int i=0;i<n;i++)//对每一个数a寻找满足a^b<max(a,b)的数b,注意a>b
{
int temp=a[i];
int j=1;//当前从右边数第j位(二进制数)
while(temp)
{
if(temp%2==0)
sum+=count[j];
temp/=2;
j++;
}
}
printf("%lld\n",sum);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: