C - Keys

lightsong發表於2024-06-06

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;
}

相關文章