CSP-J 2023 第一轮 · 客观题精讲讲义

试卷:CSP 2023 入门级(Junior)第一轮 · 单项选择 + 阅读程序 + 完善程序

用法:先独立作答,再点「显示解析」核对分步推理;右上角可切换 浅色/深色 配色。

单选题 15 阅读程序 3 段 完善程序 2 段 共 42 个作答点 答案均经代码验证

🗺️ 本卷知识地图

CSP-J 入门级第一轮。本卷可归为 8 大板块,阅读/完善程序是拉分重点。

① 语言关键字与类型

Q1 const、Q3 union 联合体、Q4 链表头插。

② 进制运算

Q2 八进制加法、Q9 二/八/十六进制互转。

③ 树与表达式

Q5 三叉树高度、Q8 后缀转中缀、Q10 哈夫曼、Q11 遍历还原。

④ 图论

Q12 拓扑排序。

⑤ 组合计数

Q6 不相邻选段、Q14 至少一女补集法。

⑥ 常识与原理

Q7 高精度、Q13 存储单位、Q15 操作系统。

⑦ 阅读程序 ⭐

海伦公式求面积、LCS+字符串旋转、因子平方和。

⑧ 完善程序 ⭐

二分查找被移除元素、编辑距离 DP。

第一部分 · 单项选择题(1–15)
第 1 题单选const

在 C++ 中,下面哪个关键字用于声明一个值不能被修改的变量?

第 2 题单选八进制加法

八进制数 123456708 和 076543218 的和为?

第 3 题单选union 联合体

union Data data; 的 value 成员存 3.14,正确写法是?

第 4 题单选链表头插

在链表头部插入 data=42 的新节点,正确操作是?

第 5 题单选三叉树高度

根节点高度为 1,一棵有 2023 个节点的三叉树高度至少为?

第 6 题单选不相邻选取

7 个时间段,选至少 1 个练歌,任意两个被选段之间至少隔 2 个空闲段。共多少种方案?

第 7 题单选高精度

以下关于高精度运算的说法错误的是?

第 8 题单选后缀转中缀

后缀表达式 6 2 3 + - 3 8 2 / + * 2 ^ 3 + 对应的中缀表达式是?

第 9 题单选进制转换

1010102 和 1668 的和为?

第 10 题单选哈夫曼编码

字符 a~f 频率为 5%,9%,12%,13%,16%,45%。哪组是对应的哈夫曼编码?

第 11 题单选遍历还原

前序 ABDECFG、中序 DEBACFG,求后序遍历。

第 12 题单选拓扑排序

DAG 有边 (1,2),(1,3),(2,4),(3,4)。哪个是有效的拓扑排序?

第 13 题单选存储单位

以下哪个描述的数据存储容量最小?

第 14 题单选补集计数

10 男 12 女选 3 人,至少含 1 个女生,有多少种组合?

第 15 题单选操作系统

以下哪个不是操作系统?

第二部分 · 阅读程序

📄 阅读程序(一)· 海伦公式求三角形面积

输入三边 a,b,c(正整数),用海伦公式 S=√(s(s−a)(s−b)(s−c)) 算面积,s 为半周长。fixed+precision(4) 固定 4 位小数。

double f(double a,double b,double c){
    double s=(a+b+c)/2;
    return sqrt(s*(s-a)*(s-b)*(s-c));     // 海伦公式
}
int main(){
   cout.flags(ios::fixed); cout.precision(4);   // 固定 4 位小数
   int a,b,c; cin>>a>>b>>c;
   cout<<f(a,b,c)<<endl;
}
16-判1判断2 分

当输入为 2 2 2 时,输出为 1.7321

16-判2判断2 分

(s-b)*(s-c) 改为 (s-c)*(s-b) 不会影响结果。

16-判3判断2 分

程序总是输出四位小数。

16-选4单选

当输入为 3 4 5 时,输出为?

16-选5单选

当输入为 5 12 13 时,输出为?

📄 阅读程序(二)· 最长公共子序列 + 字符串旋转判定

f(x,y) 是经典 LCS(最长公共子序列)DP。g(x,y):长度不同直接 false;否则判断 LCS(x+x, y)==|y|,即 y 是否为 x 的循环旋转。cout<<bool 输出 0/1。

int f(string x,string y){               // LCS 长度
    int m=x.size(), n=y.size();
    vector<vector<int>> v(m+1, vector<int>(n+1,0));
    for(int i=1;i<=m;i++) for(int j=1;j<=n;j++)
        if(x[i-1]==y[j-1]) v[i][j]=v[i-1][j-1]+1;
        else v[i][j]=max(v[i-1][j], v[i][j-1]);
    return v[m][n];
}
bool g(string x,string y){
    if(x.size()!=y.size()) return false;
    return f(x+x, y)==y.size();          // y 是 x 的旋转?
}
// main: 读 x y; 输出 g(x,y)  (0/1)
17-判1判断

f 函数的返回值小于等于 min{n, m}。

17-判2判断

f 函数的返回值等于两个输入字符串的最长公共子串的长度。

17-判3判断

当输入两个完全相同的字符串时,g 的返回值总是 true。

17-选4单选

将第 19 行 v[m][n] 替换为 v[n][m],那么该程序?

17-选5单选

当输入为 csp-j p-jcs 时,输出为?

17-选6单选

当输入为 csppsc spsccp 时,输出为?

📄 阅读程序(三)· 因子平方和

solve1(n)=n²。solve2(n) 枚举 i 到 √n,对每对因子 (i, n/i) 累加平方,i=√n 时只算一次。即 solve2(n) = n 的所有因子的平方和

int solve1(int n){ return n*n; }
int solve2(int n){
   int sum=0;
   for(int i=1;i<=sqrt(n);i++)
        if(n%i==0){
            if(n/i==i) sum+=i*i;                 // 平方根因子只算一次
            else sum+=i*i+(n/i)*(n/i);           // 一对因子 i 和 n/i
        }
    return sum;
}
// main: 输出  solve2(solve1(n))  和  solve1(solve2(n))
18-判1判断

若输入 n 为正整数,solve2 的作用是计算 n 所有因子的平方和。

18-判2判断

第 13~14 行的作用是避免平方根因子 i(或 n/i)被计算两次。

18-判3判断

若输入 n 为质数,solve2(n) 的返回值为 n²+1。

18-选4单选4 分

若输入 n 为质数 p 的平方,则 solve2(n) 的返回值为?

18-选5单选

当输入为正整数时,第一项减去第二项的差值一定?(第一项 solve2(n²),第二项 solve2(n)²)

18-选6单选

当输入为 5 时,输出为?

第三部分 · 完善程序(单选)

🧩 完善程序(一)· 二分查找被移除的元素

原是公差为 1 的等差数列(长 n+1),移除一个元素后剩 n 个。若某下标处 nums[mid] ≠ nums[0]+mid,说明缺口在左半;用二分定位被移除的值。补全 ①~⑤。

int find_missing(vector<int>& nums){
    int left=0, right=nums.size()-1;
    while(left<right){
        int mid = left+(right-left)/2;
        if(nums[mid] == mid + ) ;   // 左半完整 → 往右找
        else ;                              // 缺口在左半(含 mid)
    }
    return ;                                // 被移除的值
}
// main: if (missing == ⑤) 输出 "consecutive"; else 输出缺失值
19-①完善

① 处应填?

19-②完善

② 处应填?

19-③完善

③ 处应填?

19-④完善

④ 处(返回被移除的值)应填?

19-⑤完善

⑤ 处(判定「数列连续无缺失」的哨兵)应填?

🧩 完善程序(二)· 编辑距离(Levenshtein)

求把 str1 变成 str2 的最少操作(插入/删除/替换)次数。dp[i][j] = str1 前 i 个变成 str2 前 j 个的最少操作数。补全 ①~⑤。

int edit_dist_dp(string str1, string str2){
    int m=str1.length(), n=str2.length();
    vector<vector<int>> dp(m+1, vector<int>(n+1));
    for(int i=0;i<=m;i++) for(int j=0;j<=n;j++){
        if(i==0)        dp[i][j] = ;     // 空串 → str2 前 j 个:插 j 次
        else if(j==0)   dp[i][j] = ;     // str1 前 i 个 → 空串:删 i 次
        else if() dp[i][j] = ; // 末字符相同:免操作
        else dp[i][j] = 1 + min(dp[i][j-1], dp[i-1][j], ); // 插/删/换
    }
    return dp[m][n];
}
20-①完善

① 处应填?

20-②完善

② 处应填?

20-③完善

③ 处(判断末字符是否相同)应填?

20-④完善

④ 处(末字符相同时)应填?

20-⑤完善

⑤ 处(不同时,三种操作之一)应填?