需要推导出来一个等式

alt

这个等式是符合要求的数对,用map来统计每种符合要求的数对中数的个数。然后再从每一种数对里面符合要求数中求组合数就ok了,例如符合要求的数有3个,那么就任意从三个里面去出两个来,组合数个数就是数对的个数。 组合数是从n个数中取出m个 C(n,m)

#include<bits/stdc++.h>
using namespace std;
const int M = 2e5 + 5;
typedef long long ll;
ll a[M];
ll ans;
inline void deal() {
    map< pair<ll, ll>, ll>  mp;
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        int tmp = a[i];
        while (a[i] % 2 == 0) {
            a[i] /= 2;
        }
        mp[{tmp - log2(tmp / a[i]), a[i]}]++;
    }
    ans = 0;
    for (auto &it : mp) {
        if (it.second >= 2) {
            ans += it.second * (it.second - 1) / 2;
        }
    }

}
int main() {
    int t;
    cin >> t;
    while (t--) {
        deal();
        cout << ans << endl;
    }
}