2025 年 3 月青少年软编等考 C 语言二级真题解析
目录
- T1. 投票
- 思路分析
- T2. 千年一遇对称日
- 思路分析
- T3. 6 翻了
- 思路分析
- T4. 不变初心数
- 思路分析
- T5. 答题卡
- 思路分析
T1. 投票
题目链接:SOJ D1377
本题请你实现一个简单的投票统计工具:投票同意的人输入 1 1 1,反对的人输入 0 0 0。简单多数胜。
时间限制:1 s
内存限制:64 MB
- 输入
输入在一行中给出一系列的投票值, 1 1 1 表示同意, 0 0 0 表示反对, − 1 -1 −1 表示结束。 - 输出
统计并输出投票的结果:如果同意的人多就输出Yes;反对的人多就输出No;平票就输出Tie。
然后在第二行输出同意的人数和反对的人数,其间隔 1 1 1 个冒号:。 - 样例输入 1
1 0 0 1 1 -1 - 样例输出 1
Yes 3:2 - 样例输入 2
0 0 0 1 -1 - 样例输出 2
No 1:3 - 样例输入 3
1 1 1 0 0 0 -1 - 样例输出 3
Tie 3:3
思路分析
此题考察循环结构与分类统计,属于入门题。
此题为不定项输入,可以使用 while (cin >> ...) 来解决,当输入
−
1
-1
−1 时结束循环即可。在循环体中对输入的数据进行分类统计,循环结束后根据统计的结果进行比较输出即可。
/*
* Name: T1.cpp
* Problem: 投票
* Author: Teacher Gao.
* Date&Time: 2026/01/16 13:40
*/
#include
using namespace std;
int main()
{
ios::sync_with_stdio(false), cin.tie(0);
int cnt0 = 0, cnt1 = 0, x;
while (cin >> x && x != -1) {
if (x) cnt1++;
else cnt0++;
}
if (cnt0 < cnt1) cout << "Yes
";
else if (cnt0 == cnt1) cout << "Tie
";
else cout << "No
";
cout << cnt1 << ":" << cnt0 << endl;
return 0;
}
T2. 千年一遇对称日
题目链接:SOJ D1378
在 2021 2021 2021 年 12 12 12 月 02 02 02 日这天( 20211202 20211202 20211202),有人发了这么一张图,上书 “千年一遇对称日,万事圆满在今朝”。话是挺吉利的,但好像下一个对称日并不需要等上一千年…… 下面任给一个人的生卒年份,请你列出来这个人一辈子经过的所有对称日。
时间限制:1 s
内存限制:64 MB
- 输入
输入第一行给出一个人的名字,是由不超过 30 30 30 个字符的英文字母和空格组成的、以回车结束的非空字符串。
第二行按yyyymmdd - yyyymmdd的格式给出这个人的生卒年(yyyy)、月(mm)、日(dd)。 虽然生卒日期可能是虚构的,但题目保证出生日期在去世日期之前,且每个日期都是合法的,从00010101到99991231。
注意这里遵循四年一闰,百年不闰,四百年再闰的规则定义闰年,即年份是 4 4 4 的倍数,且不是 100 100 100 的倍数的,为普通闰年;年份是整百数的,必须是 400 400 400 的倍数才是闰年。闰年跟普通年的区别就是 2 2 2 月有 29 29 29 天。 - 输出
首先在第一行原样输出这个人的名字。
随后按照时间顺序,每行输出该人所经历的一个对称日,格式与输入格式相同。注意:生卒日期也包含在内。 - 样例输入
Katherine Johnson 19180826 - 20200224 - 样例输出
Katherine Johnson 20011002 20100102 20111102 20200202
思路分析
此题考察枚举法与数位分离,属于基础题。
可以枚举所有的合法日期,然后检测每个日期是否在给定的起止时间之内、是否是回文数即可。为了缩小枚举范围,可以先根据输入的起止时间求出年份范围。
/*
* Name: T2.cpp
* Problem: 千年一遇对称日
* Author: Teacher Gao.
* Date&Time: 2026/01/16 14:54
*/
#include
using namespace std;
int day(int year, int month) {
switch (month) {
case 4: case 6: case 9: case 11:
return 30;
case 2:
if (year % 400 == 0 || year % 100 && year % 4 == 0) {
return 29;
}
else {
return 28;
}
default:
return 31;
}
}
bool check(int x) {
int y = 0, t = x;
while (t) {
y = y * 10 + t % 10;
t /= 10;
}
return x == y;
}
int main()
{
ios::sync_with_stdio(false), cin.tie(0);
string name, x;
int L, R;
getline(cin, name);
cin >> L >> x >> R;
cout << name << endl;
int start_year = L / 10000, end_year = R / 10000;
for (int i = start_year; i <= end_year; i++) {
for (int j = 1; j <= 12; j++) {
for (int k = 1; k <= day(i, j); k++) {
int date = i * 10000 + j * 100 + k;
if (L <= date && date <= R && check(date)) {
printf("%08d
", date);
}
}
}
}
return 0;
}
T3. 6 翻了
题目链接:SOJ D1379
666 是一种网络用语,大概是表示某人很厉害、我们很佩服的意思。最近又衍生出另一个数字 9 9 9,意思是 6 6 6 翻了,实在太厉害的意思。如果你以为这就是厉害的最高境界,那就错啦 —— 目前的最高境界是数字 27 27 27,因为这是 3 3 3 个 9 9 9!
本题就请你编写程序,将那些过时的、只会用一连串 6666 … … 6 6666……6 6666……6 表达仰慕的句子,翻译成最新的高级表达。
时间限制:1 s
内存限制:64 MB
- 输入
输入在一行中给出一句话,即一个非空字符串,由不超过 1000 1000 1000 个英文字母、数字和空格组成,以回车结束。 - 输出
从左到右扫描输入的句子:如果有超过 9 9 9 个连续的 6 6 6,则将这串连续的 6 6 6 替换成 27 27 27。否则如果句子中有超过 3 3 3 个连续的 6 6 6,则将这串连续的 6 6 6 替换成 9 9 9;其他内容不受影响,原样输出。 - 样例输入
it is so 666 really 6666 what else can I say 6666666666 - 样例输出
it is so 666 really 9 what else can I say 27
思路分析
此题考察字符串遍历,属于入门题。
依次遍历字符串中的每个字符,如果该字符是 6 6 6 则进行计数,否则判断当前连续 6 6 6 的数量并进行相应的输出即可。需要注意的是,在处理完连续的 6 6 6 之后,别忘记输出当前字符,并将计数器清零。
此外,连续的 6 6 6 有可能出现在字符串末尾,为了保证这种情况下也能正确处理,应该在字符串遍历结束后再判断一次计数器是否为 0 0 0。更简单的方法是在遍历开始之前,在字符串末尾添加一个换行符,这样一来既不影响输出,也能正确处理末尾连续的 6 6 6。
/*
* Name: T3.cpp
* Problem: 6 翻了
* Author: Teacher Gao.
* Date&Time: 2026/01/16 16:13
*/
#include
#include
using namespace std;
int main()
{
string s;
getline(cin, s);
s += "
";
int cnt = 0;
for (char c : s) {
if (c == '6') {
cnt++;
}
else {
if (cnt > 0) {
if (cnt > 9) {
cout << "27";
}
else if (cnt > 3) {
cout << "9";
}
else {
for (int i = 0; i < cnt; i++) cout << '6';
}
cnt = 0;
}
cout << c;
}
}
return 0;
}
T4. 不变初心数
题目链接:SOJ D1380
不变初心数是指这样一种特别的数,它分别乘 2 、 3 、 4 、 5 、 6 、 7 、 8 、 9 2、3、4、5、6、7、8、9 2、3、4、5、6、7、8、9 时,所得乘积各位数之和却不变。例如 18 18 18 就是这样的数: 18 18 18 的 2 2 2 倍是 36 36 36, 3 + 6 = 9 3+6=9 3+6=9; 18 18 18 的 3 3 3 倍是 54 54 54, 5 + 4 = 9 5+4=9 5+4=9;…… 18 18 18 的 9 9 9 倍是 162 162 162, 1 + 6 + 2 = 9 1+6+2=9 1+6+2=9。对于 18 18 18 而言, 9 9 9 就是它的初心。本题要求你判断任一个给定的数是否有不变的初心。
时间限制:1 s
内存限制:64 MB
- 输入
输入在第一行中给出一个正整数 N N N( ≤ 100 ≤ 100 ≤100)。
随后 N N N 行,每行给出一个不超过 10 5 10^5 105 的正整数。 - 输出
对每个给定的数字,如果它有不变的初心,就在一行中输出它的初心;否则输出NO。 - 样例输入
4 18 256 99792 88672 - 样例输出
9 NO 36 NO
思路分析
此题考察数位分离,属于入门题。
对于输入的整数 x x x,首先计算出 2 x 2x 2x 的数位之和,然后依次计算 3 x 3x 3x、 4 x 4x 4x,… 9x$ 的数位和,并验证与 2 x 2x 2x 的数位和是否相等,若相等则该数位和即为初心,但凡存在一个数位和与 2 x 2x 2x 的数位和不相等则不是初心数。
/*
* Name: T4.cpp
* Problem: 不变初心数
* Author: Teacher Gao.
* Date&Time: 2026/01/16 18:30
*/
#include
using namespace std;
int calc(int x) {
int ret = 0;
while (x) {
ret += x % 10;
x /= 10;
}
return ret;
}
int main()
{
ios::sync_with_stdio(false), cin.tie(0);
int n, x;
cin >> n;
while (n--) {
cin >> x;
int sum = calc(x * 2);
bool flag = 1;
for (int i = 3; i <= 9; i++) {
int tot = calc(x * i);
if (tot != sum) {
flag = 0;
break;
}
}
if (flag) cout << sum << "
";
else cout << "NO
";
}
return 0;
}
T5. 答题卡
题目链接:SOJ D1381
新浪微博上有网友发文称:“朋友买了本玻尔 X 海森堡的物理大佬同人本,送了 300 300 300 道高数题。更绝的是,要做完题目按照答案涂答题卡,涂出一个二维码,扫描二维码才能看到特典,做错了就看不到了……” 那张传说中的答题卡如下图所示:

若答案为 4 4 4 位整数(位数不足时在前面补足 0 0 0),则前两位为横坐标,后两位为纵坐标。若一题有两小问,则第一问答案为横坐标,第二问答案为纵坐标。若答案为分数,则分子为横坐标,分母为纵坐标。
本题就请你根据答案帮助读者填写答题卡。
时间限制:1 s
内存限制:64 MB
- 输入
输入首先在第一行给出两个正整数: 2 < n ≤ 90 2 < n ≤ 90 2<n≤90 为二维码的规模,即二维码是由 n × n n × n n×n 个小方块组成的大方块,左下角的小方块对应坐标 ( 1 , 1 ) (1, 1) (1,1),右上角的小方块对应坐标 ( n , n ) (n, n) (n,n);另一个 m m m( < n 2 < n^2 <n2)是答案的个数。
随后 m m m 行,每行按以下格式之一给出一题的答案:或者是一个不超过 4 4 4 位的整数;或者是两小问的答案答案1;答案2;或者是一个分数分子/分母。这里保证每个答案都可以解析为一个二维码中的方块位置(即不存在超出二维码范围的坐标)。 - 输出
输出 n n n 行,每行 n n n 个字符,空格用.表示,涂了答案的黑格用#表示。 - 样例输入
5 7 205 3;2 4/5 101 3;3 4/3 5;1 - 样例输出
.#.#. ..... ..##. ..#.. #...#
思路分析
此题考察字符串处理与二维数组,并且涉及到坐标变换,有一定难度。
由于输入的答案可能是分数或者两个答案的形式,因此只能用字符串进行输入,之后再分别查找分号和除号,并据此确定答案在答题卡上的坐标。字符串转整数可以使用 stoi 这个函数,目前考级比赛的编译器支持比较新的 C++ 标准,使用 stoi 这个函数是允许的,在比较旧的标准上,可以先使用 c_str() 函数将 string 转换为 C 风格字符串,之后使用 atoi 这个函数将字符串转为整数。
注意到题目给出的坐标与我们习惯的二维数组下标之间是顺时针旋转 90 ° 90degree 90° 的关系,因此输出时按照列优先方式,并且从最后一列开始输出即可。
/*
* Name: T5.cpp
* Problem: 答题卡
* Author: Teacher Gao.
* Date&Time: 2026/01/17 08:44
*/
#include
using namespace std;
int main()
{
ios::sync_with_stdio(false), cin.tie(0);
int n, m;
char a[95][95] = {0};
string s;
cin >> n >> m;
for (int i = 1; i <= m; i++) {
cin >> s;
int p = s.find(';'), q = s.find('/'), x, y;
if (p != -1) {
x = stoi(s.substr(0, p));
y = stoi(s.substr(p + 1));
}
else if (q != -1) {
x = stoi(s.substr(0, q));
y = stoi(s.substr(q + 1));
}
else {
x = stoi(s) / 100;
y = stoi(s) % 100;
}
a[x][y] = '#';
}
for (int j = n; j >= 1; j--) {
for (int i = 1; i <= n; i++) {
if (a[i][j]) cout << "#";
else cout << ".";
}
cout << "
";
}
return 0;
}









