Official

D - AND and SUM Editorial by penguinman


\(x,y\) をそれぞれ二進表記したとき、両方が \(1\) となるような位の集合を \(A\)、片方が \(1\) となるような位の集合を \(B\) とします(\(2^0\) の位、\(2^1\) の位、\(\cdots\))。

まず、\(A \cap B = \emptyset\) であることは明らかです。そしてまた、\(\sum_{x \in A} x = a\)\((2 \times \sum_{x \in A} x)+(\sum_{y \in B} y)=s\) であることも分かります。

よって、\(\sum_{x \in A} x = a\)\(\sum_{y \in B} y = s-(2 \times \sum_{x \in A} x)\) と復元することができ、故に問題文中の条件を満たすような非負整数対 \((x,y)\) が存在する必要条件の \(1\) つは \(B\)\(\sum_{y \in B} y\) が一対一で対応すること(\(B\)\(\sum_{y \in B} y\) を二進数表記した際に \(1\) となるような位の集合と一致する)を踏まえると以下のようになります。

  • \(2a \leq s\) かつ \((s-2a)\ \text{AND}\ a = 0\)

そしてこの条件は、実は十分条件でもあります。\(a,s\) がこれを満たすとき、\(x=a,y=s-a\) となるような \((x,y)\) が問題文中の条件を必ず満たします。

よってこの問題を解くことができました。実装の際は各言語に備わっているビット演算を用いると便利です。

実装例 (C++)

#include<bits/stdc++.h>
using namespace std;

using ll = long long;

int main(){
	ll T; cin >> T;
	while(T--){
		ll a,s; cin >> a >> s;
		string ans = "No";
		if(2*a <= s){
			ll differ = s-2*a;
			if((differ & a) == 0) ans = "Yes";
		}
		cout << ans << endl;
	}
}

posted:
last update: