一、单项选择题
(共 15 题,每题 2 分,共 30 分。每题有且仅有一个正确选项。)
试卷解析 · 理解每一步
CSPJ-2026-R1-Mock-AI-2
试卷解析总览,可直接查看每题答案与解析。
(共 15 题,每题 2 分,共 30 分。每题有且仅有一个正确选项。)
若一个文本文件恰好包含 4096 个 ASCII 字符,且每个字符按 1 字节存储,则文件内容占用的位数为( )。
正确答案C
1 字节等于 8 位,所以内容占用 `4096 × 8 = 32768` 位。
在 Linux 终端中,以下命令能以 C++14 标准编译 `main.cpp` 并把可执行文件命名为 `run` 的是( )。
g++ -std=c++14 main.cpp -o rung++ run -o main.cpp -std=c++14./main.cpp -std=c++14 rung++ -o main.cpp run正确答案A
`-std=c++14` 指定语言标准,`-o run` 指定输出文件名,因此 A 正确。
执行下列代码后,`t` 的值是( )。 `string s = "algorithm"; string t = s.substr(2, 4);`
正确答案A
下标 2 的字符是 `g`,从此处取 4 个字符得到 `gori`。
递归函数要保证对所有合法输入都能结束,最关键的条件是( )。
正确答案D
递归必须有基本情形,并且每次调用都让问题规模向基本情形缩小,才能保证有限步结束。
依次执行 `push(3)`、`push(7)`、`pop()`、`push(5)` 后,一个初始为空的栈从栈顶到栈底依次为( )。
正确答案B
压入 3、7 后弹出栈顶 7,再压入 5,故栈顶到栈底为 5、3。
一棵非空二叉树共有 18 个结点,其中有 7 个结点恰有两个孩子,则叶结点数为( )。
正确答案C
设叶结点数为 `n0`、双孩子结点数为 `n2`,非空二叉树中恒有 `n0 = n2 + 1`,因此叶结点为 8 个。
用欧几里得算法计算 `gcd(252, 198)`,结果为( )。
正确答案C
`252 mod 198=54`,`198 mod 54=36`,`54 mod 36=18`,`36 mod 18=0`,故最大公约数为 18。
已知 `1≤n≤10^9`,`cnt` 为 `long long`。下列程序片段中,语句 `++cnt` 的执行次数数量级是( )。 `for (int i=1;i<=n;i*=2) for (int j=0;j<i;j++) ++cnt;`
正确答案B
执行次数为 `1+2+4+...+2^k`,其中 `2^k≤n<2^(k+1)`,和小于 `2n`,故为 O(n)。
执行下列代码后输出为( )。 `void f(int x, int &y){ x += 2; y += x; } int a=3,b=4; f(a,b); cout<<a<<' '<<b;`
正确答案B
`x` 是 `a` 的副本,变为 5 但不改变 `a`;`y` 引用 `b`,执行 `y += x` 后 `b=9`。
已知字符 `'0'` 到 `'9'` 的 ASCII 码连续。表达式 `'7' - '0'` 的值为( )。
正确答案A
数字字符连续编码,`'7'` 的编码比 `'0'` 大 7,因此差为整数 7。
用一维动态规划求长度为 `n` 的数组中互不相邻元素的最大和。若 `dp[i]` 表示只考虑前 `i` 个元素的最优值,最合理的转移是( )。
dp[i]=dp[i-1]+a[i]dp[i]=dp[i-2]dp[i]=min(dp[i-1],dp[i-2])+a[i]dp[i]=max(dp[i-1],dp[i-2]+a[i])正确答案D
最优方案分为不选第 `i` 个元素和选第 `i` 个元素两类;后者不能选第 `i-1` 个,因此取 `max(dp[i-1],dp[i-2]+a[i])`。
若 `x=26`,则表达式 `x & (x-1)` 的值为( )。
正确答案C
`26` 的二进制为 `11010`,`25` 为 `11001`,按位与得到 `11000`,即 24。
用字母 `A、B、C、D` 组成长度为 5 的字符串,允许重复,但相邻字符不能相同。这样的字符串共有( )个。
正确答案A
第一个位置有 4 种选择,之后每个位置不能等于前一个字符,各有 3 种选择,共 `4×3⁴` 种。
下列程序的输出是( )。 `void g(int n){ if(n==0) return; cout<<n%2; g(n/2); cout<<n%2; } int main(){ g(6); }`
正确答案D
调用顺序为 `g(6), g(3), g(1)`,递归前依次输出 `0,1,1`,回溯时依次输出 `1,1,0`,合为 `011110`。
有容量为 7 的背包,三件物品的(体积,价值)分别为 `(3,4)`、`(4,5)`、`(5,8)`,每件至多选一次。最大总价值为( )。
正确答案B
可行组合中,前两件总体积 7、价值 9;第三件单独价值 8,不能与其他物品同选,故最大值为 9。
输入字符串只含小写英文字母与字符 `#`,且不以 `#` 开头或结尾,也不存在连续的 `#`。判断题正确填 ✓,错误填 ✗。
1 | #include <algorithm>
2 | #include <iostream>
3 | #include <string>
4 | using namespace std;
5 | int main() {
6 | string s;
7 | cin >> s;
8 | string ans, part;
9 | int pal = 0;
10 | for (int i = 0; i <= (int)s.size(); ++i) {
11 | if (i < (int)s.size() && s[i] != '#') {
12 | part.push_back(s[i]);
13 | } else {
14 | string rev = part;
15 | reverse(rev.begin(), rev.end());
16 | if (rev == part) ++pal;
17 | if (!ans.empty()) ans.push_back('#');
18 | ans += rev;
19 | part.clear();
20 | }
21 | }
22 | cout << ans << '\n' << pal << '\n';
23 | return 0;
24 | }若输入不含字符 `#`,则程序仍会处理整个输入串并输出其逆序串。
正确答案正确
循环执行到 `i==s.size()` 时进入 `else`,把最后一个也是唯一一个分段逆序并加入答案。
在题目保证输入不以 `#` 开头、不以 `#` 结尾且不存在连续 `#` 时,变量 `pal` 统计回文分段的个数。
正确答案正确
每到分隔符或串尾,程序把当前分段复制并逆序;逆序后仍与原串相等恰好表示该分段是回文串。
程序输出的第一个字符串与输入字符串长度一定相同。
正确答案正确
每个分段只做逆序,字符数不变;每个原有 `#` 在拼接分段时也恰好保留一个,所以总长度不变。
输入为 `ab#level#cde` 时,程序第一行输出为( )。
正确答案A
三个分段分别逆序为 `ba`、`level`、`edc`,并按原分段顺序用 `#` 连接。
输入为 `noon#abc#x#abba` 时,程序第二行输出为( )。
正确答案C
`noon`、`x`、`abba` 是回文串,`abc` 不是,因此 `pal=3`。
设输入长度为 `n`。不计输出字符串占用的空间,程序的时间复杂度和额外空间复杂度分别是( )。
正确答案A
每个字符进入一次 `part`,各分段复制与逆序的总长度为 `n`;`part` 和 `rev` 的最大总规模为 O(n)。
输入为一个非空小写英文字母串。判断题正确填 ✓,错误填 ✗。
1 | #include <iostream>
2 | #include <string>
3 | using namespace std;
4 | string fold(const string &s, int l, int r) {
5 | if (l > r) return "";
6 | if (l == r) return string(1, s[l]);
7 | string mid = fold(s, l + 1, r - 1);
8 | if (s[l] < s[r])
9 | return s[l] + mid + s[r];
10 | else
11 | return s[r] + mid + s[l];
12 | }
13 | int main() {
14 | string s;
15 | cin >> s;
16 | cout << fold(s, 0, (int)s.size() - 1) << '\n';
17 | return 0;
18 | }对任意非空输入串,`fold` 的返回串长度与输入串长度相同。
正确答案正确
每层从两端取出两个字符,再递归处理中间部分;奇数长度最后保留中间字符,偶数长度以空串结束,因此没有增删字符。
`fold` 的最大递归深度为 O(n)。
正确答案正确
每次递归令 `l` 增 1、`r` 减 1,区间长度减少 2,所以深度约为 `n/2`,数量级为 O(n)。
若输入串本身按字符非降序排列,则输出一定与输入完全相同。
正确答案正确
非降序串的每个当前左端字符都小于或等于右端字符。相等时走 `else`,两字符相同,顺序无影响;内部区间也保持非降序,递归后整体不变。
输入为 `cabd` 时,程序输出为( )。
正确答案A
外层比较 `c` 与 `d`,返回 `c + fold("ab") + d`;内层得到 `ab`,最终输出 `cabd`。
输入为 `dbcae` 时,程序输出为( )。
正确答案B
外层 `d<e`,得到 `d...e`;内部两端为 `b` 和 `a`,交换后得到 `a + c + b`,最终为 `dacbe`。
若把程序中的字符串拼接视为按实际字符复制,`fold` 在最坏情况下的时间复杂度最接近( )。
正确答案D
递归有 O(n) 层;第 k 层构造长度与当前区间规模同阶的返回串,总复制量为 `n+(n-2)+...`,是 O(n²)。
输入为一个仅含数字字符的非空字符串,长度不超过 40。程序把它划分成若干个十进制整数,每段必须在 1~26 之间。判断题正确填 ✓,错误填 ✗。
1 | #include <iostream>
2 | #include <string>
3 | #include <vector>
4 | using namespace std;
5 | int main() {
6 | string s;
7 | cin >> s;
8 | int n = s.size();
9 | vector<long long> dp(n + 1, 0);
10 | dp[0] = 1;
11 | for (int i = 1; i <= n; ++i) {
12 | if (s[i - 1] != '0') dp[i] += dp[i - 1];
13 | if (i >= 2) {
14 | int x = (s[i - 2] - '0') * 10 + s[i - 1] - '0';
15 | if (10 <= x && x <= 26) dp[i] += dp[i - 2];
16 | }
17 | }
18 | cout << dp[n] << '\n';
19 | return 0;
20 | }`dp[i]` 表示把前 `i` 个数字字符划分成若干个 1~26 之间整数的方案数。
正确答案正确
最后一段可以由一个非零数字组成,或由 10~26 的两位数组成;程序正是把这两类来源累加到 `dp[i]`。
初始化 `dp[0]=1` 表示空前缀有一种不选任何段的方案,使后续第一个合法分段能得到正确计数。
正确答案正确
空前缀作为递推起点有一个空方案;当首位非零时,`dp[1]` 才能从 `dp[0]` 加上 1。
若输入串中出现字符 `0`,程序输出一定为 0。
正确答案错误
`0` 不能单独成段,但可以与前一个字符组成 `10` 或 `20`。例如输入 `10` 时有一种合法划分。
输入为 `12120` 时,程序输出为( )。
正确答案C
依次得到 `dp[0..5]=1,1,2,3,5,3`。末尾 0 只能与前一位组成 20,所以 `dp[5]=dp[3]=3`。
输入为 `3012`。在循环计算过程中,最小的满足 `dp[i]=0` 的正整数 `i` 是( )。
正确答案B
首位 `3` 可以单独成段,所以 `dp[1]=1`;前两位的末尾 `0` 不能单独成段,`30` 也不合法,因此 `dp[2]=0`,首次出现零状态的位置是 2。
设输入长度为 `n`,程序的时间复杂度和额外空间复杂度分别为( )。
正确答案B
循环执行 n 次,每次只做常数次运算,时间 O(n);数组 `dp` 含 n+1 个元素,额外空间 O(n)。
给定两个非空小写字母串 `s` 和 `t`(长度均不超过 30),计算从 `s` 中按原顺序选出若干字符形成 `t` 的方案数。不同下标选择视为不同方案,答案保证在 `long long` 范围内。
#include <iostream>
#include <string>
#include <vector>
using namespace std;
string s, t;
vector<vector<long long>> memo;
long long ways(int i, int j) {
if (j == (int)t.size()) return ①;
if (i == (int)s.size()) return ②;
if (memo[i][j] != -1) return ③;
long long ans = ways(④, j);
if (s[i] == t[j]) ans += ways(i + 1, ⑤);
return memo[i][j] = ans;
}
int main() {
cin >> s >> t;
memo.assign(s.size(), vector<long long>(t.size(), -1));
cout << ways(0, 0) << '\n';
return 0;
}当 `j` 已到达目标串末尾时,应把这一条递归路径计为一次成功。为实现这一含义,① 处应填( )。
01ij正确答案B
当 `j==t.size()` 时,目标串已经全部匹配完成,当前选择形成一种合法方案,应返回 1。
若目标串尚未匹配完而 `i` 已到达源串末尾,这一状态没有可行选法。② 处应填( )。
01s.size()t.size()正确答案A
目标串尚未匹配完而源串已用尽,不可能再形成匹配,方案数为 0。
缓存表的两个下标分别对应当前源串位置和目标串位置。命中缓存时,③ 处应返回( )。
memo[j][i]memo[i][j]memo[i-1][j]memo[i][j-1]正确答案B
当前子问题由源串位置 `i` 和目标串位置 `j` 唯一确定,已经计算时应直接返回 `memo[i][j]`。
第一类方案跳过 `s[i]` 而不消耗 `t[j]`。为了让源串位置恰好前进一步,④ 处应填( )。
ii + 1j + 1i - 1正确答案B
第一类方案不选择 `s[i]`,因此源串位置前进到 `i+1`,目标串位置 `j` 不变。
第二类方案选择相等的 `s[i]` 与 `t[j]` 作为一次匹配。此后目标串下标也需前进,所以⑤ 处应填( )。
jj - 1j + 1i + 1正确答案C
当 `s[i]==t[j]` 并选择该字符时,源串和目标串的下标都应前进 1,因此第二个参数是 `j+1`。
给定一个长度为 1~500 的小写字母串,求其最长回文子序列的长度。子序列不要求连续,但必须保持原字符的相对顺序。
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main() {
string s;
cin >> s;
int n = s.size();
vector<vector<int>> dp(n, vector<int>(n, 0));
for (int i = 0; i < n; ++i) dp[i][i] = ①;
for (int len = ②; len <= n; ++len) {
for (int l = 0; l + len <= n; ++l) {
int r = ③;
if (s[l] == s[r])
dp[l][r] = dp[l + 1][r - 1] + ④;
else
dp[l][r] = max(dp[l + 1][r], ⑤);
}
}
cout << dp[0][n - 1] << '\n';
return 0;
}初始化所有单字符闭区间时,其最长回文子序列就是该字符本身。① 处应赋值为( )。
01in正确答案B
单个字符自身就是长度为 1 的回文子序列,所以 `dp[i][i]=1`。
长度为 1 的区间已经完成初始化。为使转移从最短的未计算区间开始,② 处应填( )。
012n - 1正确答案C
长度为 1 的区间已经初始化,转移从长度 2 开始,逐步扩大区间。
当前枚举的是左端点为 `l`、长度为 `len` 的闭区间。由 `r-l+1=len`,③ 处应填( )。
l + lenl + len - 1len - ln - len正确答案B
长度为 `len`、左端点为 `l` 的闭区间右端点是 `l+len-1`。
当区间两端字符相等时,把它们同时接到内部回文子序列两侧。表示这两个新字符贡献的④ 处应填( )。
12lendp[l][r]正确答案B
当两端字符相等时,可在内部区间最长回文子序列的两端各加入一个字符,长度增加 2。
若两端字符不同,最优解需比较“舍去左端”和“舍去右端”两类。与 `dp[l+1][r]` 配对的⑤ 处应填( )。
dp[l][r - 1]dp[l + 1][r - 1]dp[l][r]dp[l - 1][r]正确答案A
两端不相等时,最长回文子序列至少舍去一个端点,因此在 `dp[l+1][r]` 与 `dp[l][r-1]` 中取较大值。