ABC 347
Table of Contents
D - Popcount and XOR
考察
自力で解けたが1日考えた。
$c = \mathrm{popcount}(C)$ とする。$a
$X \oplus Y = C$ のことは一旦忘れ $\mathrm{popcount}(X) = a, \mathrm{popcount}(Y) = b$ だけを考える。 $X$, $Y$ で極力同じ場所の bit を立てた場合 $\mathrm{popcount}(X \oplus Y) = |a-b|$。 $X$, $Y$ で同じ場所に bit を建てなかった場合 $\mathrm{popcount}(X \oplus Y) = a+b$ であるから $X \oplus Y = C$ になる必要条件は
$$ |a-b| \leq c \leq a+b $$である。また同じ場所に立っていた bit を別の場所で立てた場合 popcount の値は2ずつ変わるので $a+b$ と $c$ の parity は同じにならなければならない。
たとえば、下記のように $X$ の 2 bit 目の bit を下げて 4 bit 目を上げると xor を取ると popcount の値が2増える。逆に $X,Y$ のどちらかだけに立っていた bit の位置を1つの場所に移動させると popcount の値が 2 減る。 \begin{align} X = 00111 \Rightarrow X^\prime &= 10011 \nonumber \\ Y &= 01111 \nonumber \end{align}
$X, Y$ で何 bit 同じ場所に bit が立っているかを考える。考えうる popcount の最大値 $a+b$ から最終的に残したい $c$ 個を引いて、残りの bit で pair を作れば良いから $X, Y$ の $\frac{a+b-c}{2}$ 箇所 で同じところの bit が立っている。 これより $X$ の立っている bit のうち $a - \frac{a+b-c}{2}$ 箇所は $Y$ では立っていない。
解法
$X = 0$ で初期化する。
$C$ のうち bit が立っている $a - \frac{a+b-c}{2}$ 箇所を自由に選んで同じ箇所を $X$ でも立てる。
$C$ のうち bit が立っていない $\frac{a+b-c}{2}$ 箇所を自由に選んで同じ箇所を $X$ では bit を立てる。
条件に合うような bit の立て方ができなかったとき -1
を出力。
無事に bit を立て終わったら $Y = X \oplus C$ とする。
void solve() {
ll a, b, C;
cin >> a >> b >> C;
ll c = __builtin_popcountll(C);
if (c < abs(a - b) || a + b < c || (a + b) % 2 != c % 2) {
cout << -1 << endl;
return;
}
ll x = 0;
ll overrap = (a + b - c) / 2;
a -= overrap;
rep(i, 60) {
if (a && (C & (1LL << i))) {
x ^= 1LL << i;
a--;
}
}
rep(i, 60) {
if (overrap && !(C & (1LL << i))) {
x ^= 1LL << i;
overrap--;
}
}
if (a || overrap) { // これがないと 60 60 3 という入力例で WA になる
cout << -1 << endl;
return;
}
ll y = x ^ C;
cout << x << ' ' << y << endl;
}