Danik urgently needs rock and lever! Obviously, the easiest way to get these things is to ask Hermit Lizard for them.
Hermit Lizard agreed to give Danik the lever. But to get a stone, Danik needs to solve the following task.
You are given a positive integer n, and an array a of positive integers. The task is to calculate the number of such pairs (i,j) that i<j and ai & aj≥ai⊕aj, where & denotes the bitwise AND operation, and ⊕ denotes the bitwise XOR operation.
Danik has solved this task. But can you solve it?
Input
Each test contains multiple test cases.
The first line contains one positive integer t (1≤t≤10) denoting the number of test cases. Description of the test cases follows.
The first line of each test case contains one positive integer n (1≤n≤105) — length of the array.
The second line contains n positive integers ai (1≤ai≤109) — elements of the array.
It is guaranteed that the sum of n over all test cases does not exceed 105.
Output
For every test case print one non-negative integer — the answer to the problem.
Example
inputCopy
5
5
1 4 3 7 10
3
1 1 1
4
6 2 5 3
2
2 4
1
1
outputCopy
1
3
2
0
0
Note
In the first test case there is only one pair: (4,7): for it 4 & 7=4, and 4⊕7=3.
In the second test case all pairs are good.
In the third test case there are two pairs: (6,5) and (2,3).
In the fourth test case there are no good pairs.
题意:
给出长度 n 1e5的序列 ,问满足 i < j && ai & aj >= ai ^ aj 的对数 有多少
思路:
1e5 类似逆序对的问题。 位运算一般要按位来考虑
由&的性质得 两个数相与只会 小于等于 原来的数 1 & 1 = 1 1 & 0 = 0 0 & 0 = 0
由异或的性质可得 1 ^ 1 = 0 , 1 ^ 0 = 1 0 ^ 0 = 0
所以说我们只看最高位 最高位无非就两种情况 要么相等 要么不相等
相等的话 &运算 >= 异或运算 (等于是因为都为0的情况) 反之则 异或运算 > &运算
回到题目 需要满足题给条件的话 只有最高位均为1的情况 才能满足
用标记数组 记录之前该位最高位为1的情况 相加即可
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 50;
#define LL long long
LL f[55];
void db(){//二进制打表
f[0] = 1;
for(int i = 1;;i ++){
f[i] = f[i - 1] << 1;
if(f[i] > 1e9){
break;
}
}
}
int main(){
db();
int t;
cin >> t;
while(t --){
int n;
cin >> n;
vector <int> a(n);
for(int i = 0;i < n;i ++){
cin >> a[i];
}
LL res = 0;
LL vis[55] = {0};
for(int i = 0;i < n;i ++){
int top = 0;
while(f[top] <= a[i])++ top;//找到大于当前数值
res += vis[top - 1];//-1 则为当前的最高位 加上之前出现过的
vis[top - 1] ++;//加上这一次出现的
}
cout << res << '\n';
}
}