AtCoder Beginner Contest 356 C 题

72 阅读2分钟

AtCoder Beginner Contest 356 C 题

问题陈述

您有 NN 把钥匙,编号为 1,2,,N1, 2, \dots, N 。 其中一些是真钥匙,而其他的是假钥匙。

有一扇门,门 X,您可以将任意数量的钥匙插入其中。当且仅当至少插入 KK 把真钥匙时,门 X 才会打开。

您已对这些钥匙进行了 MM 次测试。第 ii \ 次测试如下:

  • 您将 CiC_i 把钥匙 Ai,1,Ai,2,,Ai,CiA_{i,1}, A_{i,2}, \dots, A_{i,C_i} 插入门 X。
  • 测试结果用一个英文字母 RiR_i 表示。
  • Ri=R_i = o 表示门 X 在第 ii \ 次测试中打开。
  • Ri=R_i = x 表示门 X 在第 ii 次测试中没有打开。

2N2^N 个可能的组合,其中哪些钥匙是真的,哪些是假的。在这些组合中,找出与任何测试结果都不矛盾的组合数。 给定的测试结果可能不正确,并且没有组合满足条件。在这种情况下,报告 00

约束

  • NNMMKKCiC_iAi,jA_{i,j} 为整数。
  • 1KN151 \le K \le N \le 15
  • 1M1001 \le M \le 100
  • 1CiN1 \le C_i \le N
  • 1Ai,jN1 \le A_{i,j} \le N
  • 如果 jkj \neq k ,则为 Ai,jAi,kA_{i,j} \neq A_{i,k}
  • RiR_iox

思路分析:

在 1~N把钥匙中有些是假的,有些是真的,真假我们不知道,每种钥匙都有两种可能的情况,0为假,1为真。

我们不是需要找到钥匙那些是真,那些是假,不要被题意给误导,我们需要找到是测试的结果是否与条件是否相矛盾,不矛盾则为真,矛盾则为假。 例如 :

  • 当真钥匙的数量小于 K 时,门可以被打开,则此组合是错误的。
  • 当真钥匙的数量大于或等于 K 时,门可以被打开,则此组合是正确的。
  • 当门没有被打开时,当真钥匙的数量大于 K 时,则此组合是错误的
  • 当门没有被打开时,当真钥匙的数量小于 K 时,则此组合是错误的 此题用位运算会比较快。
    #include<iostream>
    const int N = 110;
    int f[N];
    char r[N];
    void solve() {
        int n, m, k ;
        std::cin >> n >> m >> k;
        for(int i = 0; i < m; i++) {
            int t, x;
            std::cin >> t;
            while(t--) {
                std::cin >> x;
                x--;
                f[i] |= 1 << x; // 此代码,是第x把钥匙被测试
            }
            std::cin >> r[i];
        }
        int res = 0;
        for(int i = 0; i < 1 << n; i++) { // i < 1<<n ,二进制表示集合,表示有n把钥匙的可能的情况,用十进制的方式表示
            int ok = 1;
            for(int j = 0; j < m; j++) {
                // 假设 i 的情况是正确的
                // __builtin_popcount(i & f[j]) 枚举出正确的钥匙.
                bool t =  __builtin_popcount(i & f[j])  >= k;
                // 当 门被打开时,钥匙的数量小于 k 则为false , 
                // 当门 没有被打开,钥匙的数量大于 k ,则为false.
                if(r[j] == 'o' && !t || r[j] == 'x' && t) ok = 0;
            }
            res += ok;
        }
        std::cout << res << '\n';
    }



    int main() {
        int T = 1;
        while(T--) {
            solve();
        }
        return 0;
    }