1. 程式人生 > >ZOJ - 3870 Team Formation 異或 規律

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;
}//