桁 DP 苦手すぎる...
問題概要
整数 が与えられる。整数の組 であって、
- xor =
を満たすものの個数を求めよ。
(というテストケースが 個与えられる)
制約
考えたこと
とりあえず、 xor = という条件は
「 と を二進法表現したときに、ともに 1 が立っている桁はない」
と同値になる。そして、 という条件が嫌なので、次のように考える。
- := , , xor = を満たす の個数
とする。このとき、求める値は
と求められる。さらに、 の値は桁 DP によって求められる。
桁 DP へ
桁 DP は、「最上位桁からやる」のと「1 の位からやる」のとやり方があるけど、今回は 1 の位からやる方が楽そう。
の 1 の位を (0, 0), (1, 0), (0, 1) の 3 パターンのうちのどれにうするかを試した上で、より上位の桁の問題に帰着させていく。
#include <bits/stdc++.h> #include <sys/time.h> using namespace std; using pll = pair<long long, long long>; map<pll, long long> dp; long long func(long long a, long long b) { if (dp.count(pll(a, b))) return dp[pll(a, b)]; if (a < 0 || b < 0) return 0; if (a == 0) return b+1; if (b == 0) return a+1; long long res = 0; // (0, 0) res += func(a/2, b/2); // (0, 1) if (b % 2 == 0) res += func(a/2, b/2-1); else res += func(a/2, b/2); // (1, 0) if (a % 2 == 0) res += func(a/2-1, b/2); else res += func(a/2, b/2); return dp[pll(a, b)] = res; } int main() { int T; cin >> T; while (T--) { int l, r; cin >> l >> r; cout << func(r, r) - func(l-1, r) - func(r, l-1) + func(l-1, l-1) << endl; } }