CF2075D Equalization
CF2075D Equalization
题目描述
给定两个非负整数 x x x 和 y y y。
你可以执行以下操作任意次数(包括零次):选择一个正整数 k k k,并将 x x x 或 y y y 除以 2 k 2^k 2k(向下取整)。此操作的代价为 2 k 2^k 2k。但存在额外约束:每个 k k k 值最多只能选择一次。
你的任务是计算使 x x x 和 y y y 相等所需的最小可能代价。
输入格式
第一行包含一个整数 t t t( 1 ≤ t ≤ 1 0 5 1 \le t \le 10^5 1≤t≤105)——测试用例的数量。
每个测试用例的唯一一行包含两个整数 x x x 和 y y y( 0 ≤ x , y ≤ 1 0 17 0 \le x, y \le 10^{17} 0≤x,y≤1017)。
输出格式
对于每个测试用例,输出一个整数——使 x x x 和 y y y 相等所需的最小可能代价。
输入输出样例 #1
输入 #1
5
0 1
6 2
3 3
13 37
4238659325782394 12983091057341925
输出 #1
2
6
0
26
32764
说明/提示
第一个示例中,可以按如下步骤操作:选择 k = 1 k=1 k=1 并将 y y y 除以 2 2 2。之后, x x x 和 y y y 均等于 0 0 0。
第二个示例中,可以按如下步骤操作:选择 k = 2 k=2 k=2 并将 x x x 除以 4 4 4;选择 k = 1 k=1 k=1 并将 y y y 除以 2 2 2。之后, x x x 和 y y y 均等于 1 1 1。
第三个示例中,两数已经相等,无需操作。
翻译由 DeepSeek R1 完成
#include <bits/stdc++.h>
using i64 = long long;
void solve() {
std::array<std::array<unsigned int, 64>, 64> d;
for (auto &i : d)
for (auto &j : i) j = std::numeric_limits<unsigned int>::max();
for (unsigned int i = 0; i < (1u << 16); ++i)
for (unsigned int j = i; j; j = i & (j - 1)) {
unsigned int x = 0, y = 0;
for (unsigned int k = 0; k < 16; ++k)
if ((i >> k) & 1)
((j >> k) & 1 ? x : y) += k + 1;
if (x < 64 && y < 64)
d[x][y] = d[y][x] = std::min(d[x][y], i);
}
size_t t;
std::cin >> t;
while (t--) {
unsigned long long x, y;
std::cin >> x >> y;
if (x == y) {
std::cout << "0\n";
continue;
}
if (x < y)
std::swap(x, y);
unsigned int ans = std::numeric_limits<unsigned int>::max();
for (unsigned int i = 0; i < 58; ++i)
for (unsigned int j = 0; j < 58; ++j)
if ((x >> i) == (y >> j)) {
ans = std::min(ans, d[i][j]);
}
std::cout << ans * 2 << '\n';
}
}
int main() {
#ifdef qmwneb
assert(freopen(".in.txt", "r", stdin));
assert(freopen(".out.txt", "w", stdout));
#endif
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
solve();
return 0;
}