C - Keys
C - Keys
https://atcoder.jp/contests/abc356/tasks/abc356_c
思路
对于样例1中的两种情况,可以推知如下推论:
(1)1 2为real keys
(2)1 3 为real keys,
(3)上面两个不能同为真。
所以,上述可能得真钥匙组合为(1)(2),注意是可能,不是全部都是成立。
更一般的情况,可以把测试用例分为 正测试样例 和 负测试样例
正测试样例, 测试key集中, 必须包含 real keys(至少K个), 还可能包含 dummy keys 。
负测试样例, 测试key集中 , 可能包含 dummy keys, 也可能包含 real keys(必须小于K个)。
对于任何一组真钥匙的组合C(选择真钥匙的一结果), 要保证跟 任何 正测试样例 和 负测试样例 都没有矛盾,
则必须要保证:
(1)任一正测试样例, 组合C跟此正测试样例的钥匙交集必须包含至少K个钥匙,这些钥匙也属于组合C,顾都是真钥匙,支持此测试样例成立。
(2)任一负测试样例, 组合C跟此负测试样例的钥匙交集必须包含不多于K个钥匙, 这些钥匙也属于组合C,顾都是真钥匙,不破坏此测试样例成立性。
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; }
Code (文心一言)
现在大模型的推理能力还是很强悍的,给出的代码仅仅有两个bug,修正后pass。
原始代码:
#include <iostream> #include <vector> #include <bitset> using namespace std; // 函数用于计算一个整数中二进制1的个数 int countOnes(int mask) { int count = 0; while (mask) { count += mask & 1; mask >>= 1; } return count; } // 函数用于检查一个mask是否在给定的keys集合中至少有K个1 bool checkAtLeastKOnes(int mask, const vector<int>& keys, int K) { int count = 0; for (int key : keys) { // 检查mask的对应位是否为1 if (mask & (1 << (key - 1))) { count++; } } return count >= K; } // 函数用于检查一个mask是否在给定的keys集合中至多有K-1个1 bool checkAtMostKMinusOneOnes(int mask, const vector<int>& keys, int K) { int count = 0; for (int key : keys) { // 检查mask的对应位是否为1 if (mask & (1 << (key - 1))) { count++; } } return count <= K - 1; } int main() { int N, M, K; cin >> N >> M >> K; vector<pair<vector<int>, char>> tests(M); for (int i = 0; i < M; ++i) { int C; cin >> C; tests[i].first.resize(C); for (int j = 0; j < C; ++j) { cin >> tests[i].first[j]; } cin >> tests[i].second; } vector<int> dp(1 << N, 0); // dp数组大小为2^N // 初始化dp数组 for (int mask = 0; mask < (1 << N); ++mask) { if (countOnes(mask) >= K) { dp[mask] = 1; } } // 根据测试更新dp数组 for (const auto& test : tests) { const vector<int>& keys = test.first; char result = test.second; for (int mask = 0; mask < (1 << N); ++mask) { if (dp[mask] == 0) continue; // 如果这个状态已经被排除了,就跳过 if (result == 'o' && !checkAtLeastKOnes(mask, keys, K)) { dp[mask] = 0; // 如果结果应该是'o'但mask中1的数量不足K个,排除这个状态 } if (result == 'x' && checkAtMostKMinusOneOnes(mask, keys, K)) { dp[mask] = 0; // 如果结果应该是'x'但mask中1的数量超过或等于K个,排除这个状态 } } } // 计算答案 int answer = 0; for (int mask = 0; mask < (1 << N); ++mask) { if (dp[mask] == 1) { answer++; } } cout << answer << endl; return 0; }
改正两个bug后的代码:
https://atcoder.jp/contests/abc356/submissions/54249838
#include <iostream> #include <vector> #include <bitset> using namespace std; // 函数用于计算一个整数中二进制1的个数 int countOnes(int mask) { int count = 0; while (mask) { count += mask & 1; mask >>= 1; } return count; } // 函数用于检查一个mask是否在给定的keys集合中至少有K个1 bool checkAtLeastKOnes(int mask, const vector<int>& keys, int K) { int count = 0; for (int key : keys) { // 检查mask的对应位是否为1 if (mask & (1 << (key - 1))) { count++; } } return count >= K; } // 函数用于检查一个mask是否在给定的keys集合中至多有K-1个1 bool checkAtMostKMinusOneOnes(int mask, const vector<int>& keys, int K) { int count = 0; for (int key : keys) { // 检查mask的对应位是否为1 if (mask & (1 << (key - 1))) { count++; } } return count <= K - 1; } int main() { int N, M, K; cin >> N >> M >> K; vector<pair<vector<int>, char>> tests(M); for (int i = 0; i < M; ++i) { int C; cin >> C; tests[i].first.resize(C); for (int j = 0; j < C; ++j) { cin >> tests[i].first[j]; } cin >> tests[i].second; } vector<int> dp(1 << N, 0); // dp数组大小为2^N // 初始化dp数组 for (int mask = 0; mask < (1 << N); ++mask) { if (1) { dp[mask] = 1; } } // 根据测试更新dp数组 for (const auto& test : tests) { const vector<int>& keys = test.first; char result = test.second; for (int mask = 0; mask < (1 << N); ++mask) { if (dp[mask] == 0) continue; // 如果这个状态已经被排除了,就跳过 if (result == 'o' && !checkAtLeastKOnes(mask, keys, K)) { dp[mask] = 0; // 如果结果应该是'o'但mask中1的数量不足K个,排除这个状态 } if (result == 'x' && !checkAtMostKMinusOneOnes(mask, keys, K)) { dp[mask] = 0; // 如果结果应该是'x'但mask中1的数量超过或等于K个,排除这个状态 } } } // 计算答案 int answer = 0; for (int mask = 0; mask < (1 << N); ++mask) { if (dp[mask] == 1) { answer++; } } cout << answer << endl; return 0; }
出处:http://www.cnblogs.com/lightsong/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。