题意:
给出n个数组成的序列,求满足这样的数对的个数,i!=j,a[i]^a[j]>max(a[i],a[j]);
题解:
这题可以从二进制的角度去观察,我们可以枚举数对中的某个数i,然后计算有多少个j满足。对于j个数的计算,通过2进制数位的分析会发现,只要小于a[i]并且最高为和a[i]的对应位是不同的数就满足条件。预处理出最高位数是1的个数,剩下就是暴力枚举i和a[i]的位。
#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define B(x) (1<<(x))
using namespace std;
typedef long long ll;
void cmax(int& a,int b){ if(b>a)a=b; }
void cmin(int& a,int b){ if(b<a)a=b; }
void cmax(ll& a,ll b){ if(b>a)a=b; }
void cmin(ll& a,ll b){ if(b<a)a=b; }
void add(int& a,int b,int mod){ a=(a+b)%mod; }
void add(ll& a,ll b,ll mod){ a=(a+b)%mod; }
const int oo=0x3f3f3f3f;
const ll OO=0x3f3f3f3f3f3f3f3f;
const ll MOD=1000000007;
const int maxn = 100000 ;
int num[40],a[maxn],bit[40];
int get_bit(int n){
int dig=0;
while(n){
n/=2;
dig++;
}
return dig;
}
void Count(int n){
int bit=get_bit(n);
num[bit]++;
}
int get_bin(int n){
int len=0;
while(n){
bit[++len]=n%2;
n/=2;
}
return len;
}
int main(){
//freopen("E:\\read.txt","r",stdin);
int T,n;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
memset(num,0,sizeof num);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
Count(a[i]);
}
ll ans=0;
for(int i=1;i<=n;i++){
int len=get_bin(a[i]);
for(int j=len;j>=1;j--)
if(!(bit[j]&1))ans+=num[j];
}
cout<<ans<<endl;
}
return 0;
}