CSP-S 提高组 2025 初赛试题解析(第三部分:完善程序题(二)(39-43))
参考程序:
#include <bits/stdc++.h>
using namespace std;
long long comb(int w, int i) {if (i < 0 || i > w) {return 0;}long long res = 1;for (int t = 1; t <= i; ++t) {// 逐步乘除以避免中间溢出res = res * (w - t + 1) / t;}return res;
}// 计算长度为w、1的个数<=k的码字总数
long long count_patterns(int w, int k) {long long total = 0;for (int t = 0; t <= min(w,k); ++t) {total += comb(w, t);}return total;
}//抽象测试接口
int test_subset(const vector<vector<int>>& plan) ;int solve(int n, int k) {// ===第一步:求最小w==== int w = 1;while ( count_patterns(w,k) < n) {++w;// === ① 位置填空}cout << w << endl;// ===第二步:生成测试方案=== vector<vector<int>> code(n, vector<int>(w, 0));int idx = 0;for (int ones = 0; ones <= k && idx < n; ++ones) {// 初始化 bits:前 ones 个为 1,后面为 0,形如 [1,1,..,1,0,0,..,0]vector<int> bits(w, 0);fill(bits.begin(),bits.begin()+ones,1);// 用 do...while + prev_permutation 枚举该 ones 下的所有组合// === ② 位置填空:使用 prev_permutation(bits.begin(), bits.end()) ===do {for (int b = 0; b < w; ++b){code[idx][b] = bits[b];}++idx;if (idx >= n){break;}} while (prev_permutation(bits.begin(), bits.end()));}vector<vector<int>> plan(w);for (int i = 0; i < w; ++i) {for (int j = 0; j < n; ++j) {// === ③ 位置填空:判断第 j 条生产线在第 i 轮是否参与发货,用 code[j][i] == 1 if (code[j][i] == 1) plan[i].push_back(j);}}//===第三步:调用测试接口===int signature = test_subset(plan) ;//===第四步:结果解码=== vector<int> sig_bits(w, 0);for (int i = 0; i < w; ++i) {// === ④ 位置填空:从 signature 中取第 i 位,使用 (signature >> i) & 1 ===if ( (signature >> i) & 1 ) sig_bits[i] = 1;}for (int j = 0; j < n; ++j) {// === ⑤ 位置填空:用 vector 比较 code[j] == sig_bits if (code[j] == sig_bits) return j;}
}int main() {int n, k;cin >> n >> k; int ans = solve(n,k);cout << ans<<endl;return 0;
}