正在载入在线练习界面,本页内容可直接阅读…

AK CSP › CSP-J 2025 第一轮真题 › 第 32 题

CSP-J 2025 第一轮 第 32 题:程序(三):给 a、b 都排序后答案的变化

阅读程序 · 动态规划 · 难度 很难 · 答案 A

题目

#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;
}
CSP-J 2025 第一轮 第 32 题 原题
原题扫描(页面加载后可直接在线作答)

本小题

如果在 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号