1 条题解
-
0
我们考虑一对数 需要满足条件
从二进制最高位向最低位逐位分析。设当前比较的位为第 位(从高到低):
- 若该位上两个数均为 ,则 和 在该位均为 ,继续比较下一位。
- 若该位上一个是 ,另一个是 ,则该位上 ,,因此 ,条件不成立,可直接判定为假。
- 若该位上两个数均为 ,则该位上 ,,因此 ,条件成立,且更高位已无影响,无需再考虑低位。
记 为 的二进制表示中最高位 所在的位置(从低到高编号,最低位为 ), 类似。
- 若 ,则在第 位上 ,,由上述分析得 ,条件不成立。
- 若 ,同理条件不成立。
- 若 ,则在最高位上两个数均为 ,于是 ,条件成立。
因此,条件成立的充要条件是 ,即两个数的最高位位置相同。
于是问题转化为:统计每个数的最高位 的位置,设 表示最高位位置为 的数的个数,则答案等于所有组内两两组合数之和:
实现时只需遍历数组一次,对每个数计算其最高位(例如使用
__builtin_clz或__lg),累加对应计数,最后求和。时间复杂度 ,空间复杂度 (因为 对应最多 个不同位)。C++ 代码框架
#include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t; cin >> t; while (t--) { int n; cin >> n; vector<int> cnt(31, 0); // 最高位可能为 0 ~ 30 for (int i = 0; i < n; ++i) { int x; cin >> x; int hb = 31 - __builtin_clz(x); // 获取最高位位置 (0-based) cnt[hb]++; } long long ans = 0; for (int i = 0; i < 31; ++i) { long long c = cnt[i]; ans += c * (c - 1) / 2; } cout << ans << '\n'; } return 0; }
- 1
信息
- ID
- 6349
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 8
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者