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.
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.
For each case, print the answer in one line.
2 3 1 2 3 5 1 2 3 4 5
1 6Author: LIN, Xi
题意:给你N个数,如果两个数经过异或运算操作之后的结果,大于这两个数,那么这就是一个好的组合,问:N个数可以组成多少这样的组合。
解题思路:
我们先看组二进制的数:
1010
①如果与一个比他小的数字进行异或运算之后的值要大于1010本身,那么我们找的数的最高位不能为1。
②所以我们考虑到100 101 110 111.。这四个数字与1010 进行异或之后的值都大于1010本身。这几个数的共同特点就是最高位是1,并且1010这个数这一位上的数等于0.
如果是10 11 这异或之后肯定小于1010;
如果最后一位是1 那么异或后也大于1010;
所以,如果
每个数考虑成2进制,我们可以求出,一个数a的最高位的1所在的位置i。如果i之后的某一位置j上的数字为0,如果有一个数b最高位1为当前这个位置j。那么这个数和a进行异或运算肯定大于他们两个的值。我们可以标记最高位为L的数的数量。如果j位置为0,那么我们可以将所有数最高位为j的数字数量加入ans。因为是取最高位,所以不会查找到相同组合的。
AC代码:
#include <stdio.h> #include <math.h> #include <vector> #include <queue> #include <string> #include <string.h> #include <stdlib.h> #include <iostream> #include <algorithm> using namespace std; const int MAXN = 100000+10; int a[MAXN],M_bit[MAXN]; void f(int x) { int L=31; while(L>=0){ if(x&(1<<L)){ M_bit[L]++; return; } L--; } return; } int main() { int T,N; scanf("%d",&T); while(T--){ scanf("%d",&N); memset(M_bit,0,sizeof(M_bit)); for(int i=0;i<N;i++){ scanf("%d",&a[i]); f(a[i]); } long long ans=0; for(int i=0;i<N;i++){ int L=31; while(L){ if(a[i]&(1<<L)) break; L--; } L--; while(L>=0){ if(!(a[i]&(1<<L))) ans+=M_bit[L]; L--; } } printf("%lld\n",ans); } return 0; }