题目大意
给定 和 ,现在要你找到两个正整数 和 ,使得 的对应二进制数当中 的个数为 , 的对应二进制当中 的个数为 ,以及 。
解法
首先,我们知道 和 ,然后考虑构造方案。不如先令 ,那么很显然 。接下来考虑如何满足条件一二,我们可以将 的一些位置上面的 移动到 上面,这样子 仍等于 。但是有可能位数不够用,这时候我们就需要找到一些 和 都等于 的位置,然后把这个位置上面的数都改成 ,这样子 也是等于 的。
为了让他们尽量匹配,在把 的 移到 身上的时候,我们需要尽量的匀称,简单来说就是让 尽量接近 。
具体操作请看代码。
代码
#include <iostream>
#include <bitset>
using namespace std;
using LL = unsigned long long;
const LL kMaxN = 2e5 + 5;
LL a, b, c;
bitset<60> x, y;
int main() {
cin >> a >> b >> c;
x = c; // 先令 x = c
LL cnt = 0, res = (x.count() + b - a) / 2; // 计算需要移多少个
for (LL i = 0; cnt < res && i < 60; i++) { // 移动 res 次
if (x[i]) { // 如果可以移
x[i] = 0, y[i] = 1; // 移过去
cnt++; // 计数器累加
}
}
cnt = 0, res = a - x.count(); // 清空并计算要填多少个 1
for (LL i = 0; cnt < res && i < 60; i++) { // 填 1
if (!x[i] && !y[i]) { // 找空的地方填
x[i] = y[i] = 1; // 填上去
cnt++; // 计数器累加
}
}
if (x.count() != a || y.count() != b || (x.to_ullong() ^ y.to_ullong()) != c) {
cout << "-1\n";
} else {
cout << x.to_ullong() << ' ' << y.to_ullong() << '\n';
}
return 0;
}