题意:
给n个数,问从n个数中选出两个数构成二元组(a[i],a[j])且i不等j,并且(a[j],a[i])和 (a[i],a[j])算一组。
求使得 a[i]亦或a[j]>max(a[i],a[j]) 的二元组个数。
思路:
bit[i]数组记录二进制最高位是i(就是最高位是第i位且是1)的数有多少个。
遍历所有的数。默认遍历的数是a[i],a[j]中较大的那个。
那么我们只要寻找比它小的且亦或值会大于它的数有多少个就好了。
接着对于一个数转换成 二进制,比如10100。
那么ans=bit[0]+bit[1]+bit[3]就好了。
就是最高位之后是0的位的和。
因为10100的最高位数4.
那么最高位是3、2、1、0的数就一定比它小了。
那么他们的第4位就是0那么亦或出来的第4位就一定是1.
那么接着只要0的地方是1就好了。这样比如第3位是1.
那么亦或出来的结果就一定是11xxx一定大于10100了。
代码:
#include"cstdlib"
#include"cstdio"
#include"cstring"
#include"cmath"
#include"queue"
#include"algorithm"
#include"iostream"
#include"map"
#include"vector"
using namespace std;
int bit[33];
int v[123456];
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
scanf("%d",&n);
memset(bit,0,sizeof(bit));
for(int i=0; i<n; i++)
{
scanf("%d",&v[i]);
for(int j=30; j>=0; j--)
{
if((1<<j)&v[i])
{
bit[j]++;
break;
}
}
}
int ans=0;
for(int i=0; i<n; i++)
{
int j;
for(j=30; j>=0; j--)
{
if((1<<j)&v[i]) break;
}
for(j=j;j>=0;j--)
{
if(!((1<<j)&v[i])) ans+=bit[j];
}
}
printf("%d\n",ans);
}
return 0;
}