正在载入在线练习界面,本页内容可直接阅读…
AK CSP › CSP-J 2025 第一轮真题 › 第 32 题
CSP-J 2025 第一轮 第 32 题:程序(三):给 a、b 都排序后答案的变化
题目
#include <algorithm>
#include <cstdio>
#include <cstring>
#define ll long long
int f[5007][5007];
int a[5007], b[5007];
int n;
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
}
for (int i = 1; i <= n; ++i) {
scanf("%d", &b[i]);
}
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
f[i][j] = std::max(f[i][j], std::max(f[i - 1][j], f[i][j - 1]));
if (a[i] == b[j]) {
f[i][j] = std::max(f[i][j], f[i - 1][j - 1] + 1);
}
}
}
printf("%d\n", f[n][n]);
return 0;
}
本小题
如果在 16 行的循环前加上以下两行: std::sort(a+1, a+n+1); std::sort(b+1, b+n+1); 则答案会( )。
选项
- A. 变大或不变
- B. 变小或不变
- C. 一定变大
- D. 不变
答案
A
题解
选 A.变大或不变。
这段程序求的是两个数组的最长公共子序列(LCS)长度。子序列可以不连续,但必须保持原来的先后顺序。
假设某个数 \(x\) 在 a 中出现 \(c_a(x)\) 次,在 b 中出现 \(c_b(x)\) 次,那么公共子序列中最多包含 \[ \min(c_a(x),c_b(x)) \] 个 \(x\)。因此,原答案一定满足: \[ \text{原答案}\le \sum_x \min(c_a(x),c_b(x)). \]
两个数组都排序后,所有数的顺序一致,每种数都可以取两边出现次数的较小值,拼成一个公共子序列。所以: \[ \text{排序后答案}=\sum_x \min(c_a(x),c_b(x))\ge \text{原答案}. \]
例如:
- 变大:
a = [1, 2],b = [2, 1]。原答案为 1,排序后为 2。 - 不变:
a = [1, 2],b = [1, 2]。排序前后答案都是 2。
因此,答案可能变大,也可能不变。
真题版权归 CCF 所有,本站仅用于非商业教学用途。页面加载后可直接在线作答,作答记录保存在本浏览器或账号中。 京ICP备2026056990号-1
京公网安备11010502062986号