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{AB}).

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

題意:

說是給你一個數組。要求兩兩結合。然後做異或運算處理。如果異或結果>這兩個數最大的,ans ++;

這道題做的時候想的有點多,最開始取到每個元素的最低位。看看get_sum();函數,裏面是我最初的想法。

但是想一下,只要控制它的最高位就可以了。舉個例子。比如說

10111 和 1111 也就是23和15異或等於多少等於11000,長度都是以大的爲基準,然後看23的二進制位中的‘0’位,

異或之後變爲‘1’,而‘0’位之後的所有的‘1’在和1111異或之後全部變爲‘0’。減少了111,而增加了1000,所以說

異或的結果還會大於最大的值,所以只要控制沒個數的最高位的‘1’所在位置,判斷與它異或的數的二進制的同一位是否爲‘0’即可。



#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <stack>
#include <map>
#include <vector>
#include <cmath>
#include <algorithm>

using namespace std;

#define MAX_N 100005
#define INF 0x3f3f3f3f
#define Mem(a,x) memset(a,x,sizeof(a))
#define ll long long

int p[MAX_N],w[MAX_N],len[MAX_N];
int cur[100];
int get_bit(int x) {
    int res = 1;
    while(x) {
        int r = x ^ 1;
        if(r % 2 == 0) break;
        x >>= 1;
        res ++;
    }
    return res;
}
int get_num(int x,int d) {

    if(d == 1) {
        x ^= 1;
        if(x%2 == 0) return 1;
        return 0;
    }
    int tmp = 1;
    while(x) {
        x>>=1;
        tmp ++;
        if(tmp == d) break;
    }
    int t = x ^ 1;
    if(t % 2 == 1) return 0;
    return 1;
}
int get_len(int x) {

    int res = 0;
    while(x) {
        x >>= 1;
        res ++;
    }
    return res;
}
int get_sum(int x)
{
    int ans = 0;
    for(int i = 0; i<x; i++) {
        int num = get_num(p[x],len[i]);
        if(num == 0 || (len[x] > len[i] && w[i] != w[x])) {
                //cout<<p[i]<<' '<<w[i]<<endl;
            ans ++;
        }
    }
    //cout<<endl;
    return ans;
}
int main()
{
//    for(int i = 1; i<10; i++) {
//        cout<<i<<' '<<get_num(i,1)<<endl;
//    }
    int n;
    while(cin>>n)
    {
        while(n--)
        {
            Mem(cur,0);
            int m,ans = 0;
            cin>>m;
            Mem(w,0);
            Mem(len,0);
            for(int i = 0; i<m; i++)
            {
                scanf("%d",&p[i]);
            }
            //sort(p,p+m);
            for(int i = 0; i<m; i++) {
                //w[i] = get_bit(p[i]);
                len[i] = get_len(p[i]);
                cur[len[i]] ++;
            }
           // for(int i = 1; i<=10; i++) cout<<i<<' '<<cur[i]<<endl;
            for(int i = 0; i<m; i++)
            {
                //cout<<p[i]<<' '<<w[i]<<endl;

                int lon = len[i];
                //cout<<p[i]<<"    "<<lon<<endl;
                for(int j = lon-1; j>=1; j--) {
                    if(get_num(p[i],j) == 0) {
                            //cout<<p[i]<<' '<<cur[j]<<endl;
                        ans += cur[j];
                    }
                }
            }
            printf("%d\n",ans);
        }
    }
    return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章