正在载入在线练习界面,本页内容可直接阅读…
AK CSP › CSP-S 2026 第一轮真题 › 第 43 题
CSP-S 2026 第一轮 第 43 题:标准答案:⑤处应填
题目
给定 $n$ 名学生参加一场考试,考试共有 $m$ 道选择题,每道题只有 A、B 两个选项。
第 $i$ 名学生的作答为一个长度为 $m$ 的字符串。若最终公布的标准答案与该学生在某道题上的作答相同,则该学生在这道题上得 1 分,否则不得分。记第 $i$ 名学生最终得到的总分为 $r_{i}$。
每名学生还有一个预期得分 $x_{i}$。现在需要构造一份标准答案,使
尽可能大。
数据满足 $1 \le n \le 18$,$1 \le m \le 300$,$0 \le x_{i}\le m$。
提示:可以换一个角度处理 $\sum_{i=1}^{n}∣r_{i}- x_{i}∣$,把它写成更易优化的形式;对正整数 $x$,__builtin_ctzll(x) 返回 $x$ 的二进制表示末尾连续 0 的个数;__builtin_popcountll(x) 返回 $x$ 的二进制表示中 1 的个数。
以下程序构造出一组满足要求的标准答案。请补全程序。
#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
int main() {
int n, m;
cin >> n >> m;
vector<ll> x(n), c(n);
for (int i = 0; i < n; i++) {
cin >> x[i];
c[i] = /* ① */;
}
vector<string> a(n);
for (int i = 0; i < n; i++)
cin >> a[i];
vector<int> s(n, -1);
vector<ll> q(m, 0);
ll C = 0, S = 0;
for (int i = 0; i < n; i++) {
C -= c[i];
for (int j = 0; j < m; j++) {
if (a[i][j] == 'A') q[j]--;
else q[j]++;
}
}
for (int j = 0; j < m; j++) S += abs(q[j]);
ll ans = C + S;
ull best = 0, lst = 0;
for (ull mask = 1; mask < (1ULL << n); mask++) {
ull g = /* ② */;
ull d = g ^ lst;
int k = /* ③ */;
C -= /* ④ */;
for (int j = 0; j < m; j++) {
ll old = q[j];
int v = (a[k][j] == 'A' ? 1 : -1);
q[j] -= 2ll * s[k] * v;
S += abs(q[j]) - abs(old);
}
s[k] = -s[k];
if (C + S > ans) {
ans = C + S;
best = g;
}
lst = g;
}
for (int i = 0; i < n; i++) {
if ((best >> i) & 1) s[i] = 1;
else s[i] = -1;
}
string res(m, 'A');
for (int j = 0; j < m; j++) {
ll v = 0;
for (int i = 0; i < n; i++) {
if (a[i][j] == 'A') v += s[i];
else v -= s[i];
}
if (/* ⑤ */) res[j] = 'A';
else res[j] = 'B';
}
cout << res << endl;
return 0;
}本小题
⑤处应填( )。
选项
- A. v >= (n & 1)
- B. v > (n & 1)
- C. v + (n & 1) >= 0
- D. v * (n & 1) >= 0
答案
A
题解
答案是 A.v >= (n & 1)。
关键是把绝对值改写成: \[ |r_i-x_i|=\max_{s_i\in\{-1,1\}}s_i(r_i-x_i). \] 因此,可以枚举每个学生对应的符号 \(s_i\),再求这组符号下最优的标准答案。代码前半部分就是在枚举符号,并用 best 保存最优的一组。
固定 \(s_i\) 后,要最大化 \[ \sum_i s_i(r_i-x_i). \] 其中 \(-\sum_i s_ix_i\) 是常数,所以每道题都可以独立选择答案。
对于第 \(j\) 道题:
- 标准答案选 A,这道题对上式的贡献是 \(\sum_{a_{ij}=\mathrm A}s_i\);
- 标准答案选 B,贡献是 \(\sum_{a_{ij}=\mathrm B}s_i\)。
两者相减,恰好是程序计算的 \[ v=\sum_{a_{ij}=\mathrm A}s_i-\sum_{a_{ij}=\mathrm B}s_i. \] 所以 \(v\ge 0\) 时选 A,\(v<0\) 时选 B;\(v=0\) 时两种答案都可以。
为什么选项 A 等价于 v >= 0?因为 \(v\) 是 \(n\) 个 \(+1\) 或 \(-1\) 的和,其奇偶性与 \(n\) 相同:
| \(n\) 的奇偶性 | n & 1 | 选 A 的条件 |
|---|---|---|
| 偶数 | 0 | \(v\ge 0\) |
| 奇数 | 1 | \(v\ge 1\),因为此时 \(v\) 不可能为 0 |
因此⑤应填: ``cpp v >= (n & 1) ``
其他选项的问题:B 在 \(n\) 为奇数、\(v=1\) 时错误地选 B;C 在 \(n\) 为奇数、\(v=-1\) 时错误地选 A;D 在 \(n\) 为偶数时总是选 A。
真题版权归 CCF 所有,本站仅用于非商业教学用途。页面加载后可直接在线作答,作答记录保存在本浏览器或账号中。 京ICP备2026056990号-1
京公网安备11010502062986号