ZOJ - 3870 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

题意:任选两个位置的数,异或值大于他们两个数

题解:举个例子:比如10100, 我们找比这个数小, 与这个数异或得到更大的数,每位从高位到低位看 ,首先第一位肯定要为0,第二位,可以为1,也可以为0,当第二位为1时,后边的数就无所谓了,因为已经比10100大了,得到一个01***;当第二位为0时,第三位必须为0,第4位可以为0,也可以为1,为1时后面无所谓,得到0001*,当第4位为0时,第5位必须为1,得到00001

综上,由10100,我们得到 01***,0001*,00001 与10100异或得到更大的结果,我们发现,得到的这3类数,是由10100为0位得到的,并且该位为1且是首位为1,细想一下成立,在给10100找有多少种的时候,如果该数首位1的位置,在10100为1,那肯定得到更小的数,如果为0,那肯定得到更大的数,因此我们记录每个数首位为1的位置,对于每个数加上为0位置已经记录多少即可

注意要先排序,因为我们是找比这个数小的

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
#define lowbit(x) x&(-x)
typedef long long ll;
int num[35];
int a[100100];
int n,x;
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        cin>>n;
        memset(num,0,sizeof(num));
        ll ans=0;
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        sort(a+1,a+1+n);
        for(int i=1;i<=n;i++)
        {
            x=a[i];
            int cnt=x;
            int k=1;
            while(cnt)
            {
                if(cnt%2==0) ans+=num[k];
                cnt/=2;
                if(cnt==0) num[k]++;
                k++;
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}//

猜你喜欢

转载自blog.csdn.net/mmk27_word/article/details/84619060
ZOJ