ログインしてください。
公式
E - 共通部分/Intersection 解説
by
E - 共通部分/Intersection 解説
by
Nyaan
この問題は次の手順によって解くことが出来ます。
- 答えを \(\mathrm{answer}\) とする。\(\mathrm{answer}\) ははじめ \(0\) で初期化されている。
- 全ての 2 個以上の整数集合の部分集合を列挙する。各部分集合に対して次の操作を行う。
- 整数集合の共通部分を求める。
- 共通部分が奇数のみで構成されている場合、\(\mathrm{answer}\) に \(1\) を加算する。
- 操作後の \(\mathrm{answer}\) が答えとなる。
計算量は \(\mathrm{O}(2^N \max(C))\) 程度で十分高速です。
- 実装例 (C++)
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
int main() {
int N;
cin >> N;
vector<vector<int>> A(N);
for (auto& x : A) {
int C;
cin >> C;
x.resize(C);
for (auto& y : x) cin >> y;
}
auto intersect = [](vector<int> a, vector<int> b) {
vector<int> c;
set_intersection(begin(a), end(a), begin(b), end(b), back_inserter(c));
return c;
};
int ans = 0;
for (int b = 0; b < (1 << N); b++) {
if (__builtin_popcount(b) < 2) continue;
vector<int> v = A[__builtin_ctz(b)];
for (int i = 0; i < N; i++) {
if ((b >> i) & 1) v = intersect(v, A[i]);
}
ans += all_of(begin(v), end(v), [](int x) { return x % 2 == 1; });
}
cout << ans << endl;
}
投稿日時:
最終更新:
