C - Keys
https://atcoder.jp/contests/abc356/tasks/abc356_c
思路
對於樣例1中的兩種情況,可以推知如下推論:
(1)1 2為real keys
(2)1 3 為real keys,
(3)上面兩個不能同為真。
更一般的情況,可以把測試用例分為 正測試樣例 和 負測試樣例
正測試樣例, 測試key集中, 必須包含 real keys(至少K個), 還可能包含 dummy keys 。
負測試樣例, 測試key集中 , 可能包含 dummy keys, 也可能包含 real keys(必須小於K個)。
對於任何一組鑰匙的組合C(選擇鑰匙的一結果), 要保證跟 任何 正測試樣例 和 負測試樣例 都沒有矛盾,
則必須要保證:
(1)任一正測試樣例, 組合C跟此正測試樣例的鑰匙交集必須包含至少K個鑰匙
(2)任一負測試樣例, 組合C跟此正測試樣例的鑰匙交集必須包含不多於K個鑰匙
Code
https://atcoder.jp/contests/abc356/submissions/54250649
int n,m,k; int main() { cin >> n >> m >> k; vector<int> a(m); vector<bool> r(m); for(int i=0; i<m; i++){ int c; cin >> c; for(int j=0; j<c; j++){ int key; cin >> key; key--; a[i] |= 1 << key; } char test; cin >> test; r[i] = test == 'o'? true : false; } // iterate all combinations int maxc = 1 << n; int ans = 0; for(int i=0; i<maxc; i++){ bool contradict = false; for(int j=0; j<m; j++){ int overlap = i & a[j]; // count 1 number int keycnt = 0; while(overlap){ if (overlap & 1){ keycnt++; } overlap >>= 1; } if (r[j] && keycnt>=k){ continue; }else if (!r[j] && keycnt<k){ continue; } contradict = true; break; } if (!contradict){ ans++; } } cout << ans << endl; return 0; }