2023 年 3 月青少年软编等考 C 语言二级真题解析
目录
- T1. 数字字符求和
- 思路分析
- T2. 简单密码
- T3. 进阶的卡莎
- 思路分析
- T4. 合影效果
- T5. 割圆
- 思路分析
T1. 数字字符求和
请编写一个程序实现以下功能:从一个字符串中,提取出所有的数字字符即 0 ∼ 9 0 \sim 9 0∼9,并作为数求和。
时间限制:1 s
内存限制:64 MB
- 输入
一行字符串,长度不超过 100 100 100,字符串中不含空格。 - 输出
字符串中所有数字字符作为数的和。 - 样例输入
Lsd2f02k3ja3sdf223
- 样例输出
17
思路分析
此题考查字符串操作,属于入门题。
依次遍历每一个字符 s[i]
,若该字符处于 '0' ~ '9'
范围,则将 s[i] - '0'
累加到答案中即可。
/*
* Name: T1.cpp
* Problem: 数字字符求和
* Author: Teacher Gao.
* Date&Time: 2024/11/15 23:22
*/
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s;
int sum = 0;
cin >> s;
for (int i = 0; i < s.size(); i++) {
if ('0' <= s[i] && s[i] <= '9') {
sum += s[i] - '0';
}
}
cout << sum;
return 0;
}
T2. 简单密码
此题为 2020 年 12 月二级第二题原题,见 2020 年 12 月青少年软编等考 C 语言二级真题解析中的 T2。
T3. 进阶的卡莎
虚空之女·卡莎考入了战斗学院,她的父亲虚空行者·卡萨丁要检查她的考试成绩。已知卡莎一段时间内的成绩序列,请你帮卡萨丁计算卡莎在这段时间内最长的成绩连续上升(相等不算做连续上升)的长度。
例如,给出卡莎的成绩序列是 85 90 80 85 90 95 95 80 75 75 85\ 90\ 80\ 85\ 90\ 95\ 95\ 80\ 75\ 75 85 90 80 85 90 95 95 80 75 75,其中连续上升序列包括 85 90 85\ 90 85 90 和 80 85 90 95 80\ 85\ 90\ 95 80 85 90 95 两组,后者是最长的连续上升成绩序列(相等不算做连续上升),应该输出后者的长度 4 4 4。
时间限制:1 s
内存限制:64 MB
- 输入
输入的第一行是序列的长度 n n n, 1 ≤ n ≤ 100 1 \le n \le 100 1≤n≤100。
第二行给出序列中的 n n n 个整数,这些整数的取值范围都在 0 0 0 到 100 100 100。 - 输出
最长的成绩连续上升的长度(相等不算做连续上升)。 - 样例输入
10 85 90 80 85 90 95 95 80 75 75
- 样例输出
4
思路分析
此题考查尺取法,难度入门。
定义 L L L 表示当前尺取起点,初始值为 1 1 1,此处用临时变量 t t t 来表示上一个数据,从而避开数组,初始值为 − 1 -1 −1,确保第一个元素顺利进入尺取范围。
每次输入一个数 x x x,若 x x x 不大于上一个数 t t t,表明当前尺取范围结束,用 i − L i-L i−L 更新答案,同时更新尺取起点 L L L 为 i i i。注意循环结束后需要做最后一次答案更新。
/*
* Name: T3.cpp
* Problem: 进阶的卡莎
* Author: Teacher Gao.
* Date&Time: 2024/11/15 23:24
*/
#include <iostream>
using namespace std;
int main(){
int n, x, t = -1;
int L = 1, ans = 0;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> x;
if (x <= t) {
ans = max(ans, i - L);
L = i;
}
t = x;
}
ans = max(ans, n - L + 1);
cout << ans;
return 0;
}
T4. 合影效果
此题为 2020 年 9 月二级第四题原题,见 2020 年 9 月青少年软编等考 C 语言二级真题解析中的 T4。
T5. 割圆
本题将实现一个简化版的 “割圆” 游戏。成功点亮所有灯时,联结第一个和最后一个灯称之为 “割线”。
n n n 盏灯环形分布,顺序编号为 1 1 1 到 n n n。灯的初始状态为关闭不亮。假设 n n n 为 7 7 7,则第 1 1 1 号灯与第 2 2 2、 7 7 7 号灯相邻,第 2 2 2 号灯与第 1 1 1、 3 3 3 号灯相邻,以此类推。
灯的点亮规则如下:
- 输入 m m m 个数,每个数为某个灯的编号,可能重复或只是部分编号;
- m m m 个数中的第 1 1 1 个数所对应的灯,默认点亮;
- 如果输入数对应灯的左侧或右侧已被点亮,则点亮自身。否则啥也不做;
- 如果所有的灯都已被点亮,则程序结束, m m m 个数中尚未被处理的数将不再处理;
- 输出第 1 1 1 次和最后一次点亮灯的编号;
- 如果
m
m
m 个数处理完毕尚未点亮所有灯,则输出
No
。
时间限制:1 s
内存限制:64 MB
- 输入
第一行 2 2 2 个整数 n n n, m m m,保证 3 ≤ n ≤ 1000 3 \le n \le 1000 3≤n≤1000, 1 ≤ m ≤ 10000 1 \le m \le 10000 1≤m≤10000。
第二行 m m m 个数,每个数都在 1 1 1 到 n n n 之间,表示输入序列。 - 输出
如果完成了 “割圆”,则输出两个整数,之间用一个空格隔开,否则输出No
。 - 样例输入
7 10 2 3 1 7 5 6 5 4 4 2
- 样例输出
2 4
- 提示
第 1 1 1 个数 2 2 2,直接被点亮;
第 2 2 2 个数 3 3 3, 3 3 3 与已亮的 2 2 2 相邻,被点亮;
第 3 3 3 个数 1 1 1, 1 1 1 与已亮的 2 2 2 相邻,被点亮;
第 4 4 4 个数 7 7 7, 7 7 7 与已亮的 1 1 1 相邻,被点亮;
第 5 5 5 个数 5 5 5, 5 5 5 与 4 4 4 和 6 6 6 相邻,但 4 4 4 和 6 6 6 都没亮,什么都不做;
第 6 6 6 个数 6 6 6, 6 6 6 与已亮的 7 7 7 相邻,被点亮;
第 7 7 7 个数 5 5 5, 5 5 5 与已亮的 6 6 6 相邻,被点亮;
第 8 8 8 个数 4 4 4, 4 4 4 与已亮的 5 5 5 相邻,被点亮;
此时,所有的数都被点亮,第 1 1 1 个点亮的是 2 2 2,最后点亮的是 4 4 4。
思路分析
此题考查数组标记法(模拟法),难度入门。
设置数组 f f f 标记每盏灯的状态,初始为 0 0 0。第一盏灯可以单独处理,之后每一盏灯 x x x 输入之后检测 f [ x ] f[x] f[x],若为 1 1 1 则不做任何处理,否则检测 f [ x − 1 ] f[x-1] f[x−1] 和 f [ x + 1 ] f[x+1] f[x+1],若为 1 1 1 则将 f [ x ] f[x] f[x] 置为 1 1 1,并且计数器累加 1 1 1。若计数器到达 n n n,则更新答案,并提前结束循环。
为了便于处理第 1 1 1 盏灯和第 n n n 盏灯相邻的情况,可以在检测 f [ x − 1 ] f[x-1] f[x−1] 和 f [ x + 1 ] f[x+1] f[x+1] 之前,用 f [ 0 ] = f [ n ] , f [ n + 1 ] = f [ 1 ] f[0] = f[n], f[n+1] = f[1] f[0]=f[n],f[n+1]=f[1] 进行更新。
/*
* Name: T5.cpp
* Problem: 割圆
* Author: Teacher Gao.
* Date&Time: 2024/11/15 23:33
*/
#include <iostream>
using namespace std;
int main()
{
int n, m, x;
int f[1005] = {0}, L, R = 0, tot = 1;
cin >> n >> m >> L;
f[L] = 1;
for (int i = 2; i <= m; i++) {
cin >> x;
if (f[x]) continue;
f[0] = f[n], f[n+1] =f[1];
if (f[x-1] || f[x+1]) {
f[x] = 1;
tot++;
}
if (tot == n) {
R = x;
break;
}
}
if (R) cout << L << " " << R;
else cout << "No";
return 0;
}