位运算

题目大意

给定 ,现在要你找到两个正整数 ,使得 的对应二进制数当中 的个数为 的对应二进制当中 的个数为 ,以及

解法

首先,我们知道 ,然后考虑构造方案。不如先令 ,那么很显然 。接下来考虑如何满足条件一二,我们可以将 的一些位置上面的 移动到 上面,这样子 仍等于 。但是有可能位数不够用,这时候我们就需要找到一些 都等于 的位置,然后把这个位置上面的数都改成 ,这样子 也是等于 的。

为了让他们尽量匹配,在把 移到 身上的时候,我们需要尽量的匀称,简单来说就是让 尽量接近

具体操作请看代码。

代码

#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;
}