简介:2024年第三十一届厦门市小学生计算机C++语言竞赛(初赛)试题,是一份面向小学高年级信息学初学者的完整真题试卷。全卷共四大题、45小题,满分100分,限时90分钟,内容涵盖计算机基础知识、C++语法、进制转换、数据类型、循环与数组、递归函数及算法逻辑,并融入诺贝尔奖、量子通信、空间科学等科技热点,适合用于竞赛选拔训练、C++知识巩固与备赛自测。资源为1个PDF文件,压缩包大小约301KB,版面清晰、题目完整,可直接打印或屏幕阅读。已有189人学习下载。通过这份试卷,读者既能感受真实初赛的题型与难度,也能系统检验对程序执行流程、函数调用、逻辑推导等核心考点的掌握情况;建议按考试时间限时作答,之后逐题分析推导过程,结合编程实际运行验证,有效提升综合解题能力。
1. 2024年第三十一届某市小学生计算机C++语言竞赛:初赛试题到底在考什么
先说一个反直觉的结论:初赛试卷里最拉分的不是压轴算法题,而是前面的基础题。2024年第三十一届某市小学生计算机C++语言竞赛(初赛)试题整体难度平稳,但覆盖面比很多家长想得更宽。初赛通常以笔答为主,不像机试那样能反复试探,它要求孩子在纸上完成“读题、手算、读程序、补代码”整个流程。换句话说,初赛筛的不是谁见过更多难题,而是谁的基本功更扎实。这篇文章适合正在学 C++ 的小学高年级学生,也适合带竞赛入门班的老师。把初赛的题型、训练方法和常见坑说清楚,后面的备赛才不会白忙。
2. 初赛到底考什么:一套笔试卷子拆成四类必练题型
2.1 选择题:运算符优先级和数据范围是固定丢分点
选择题通常出现在前 10 到 15 题,知识点很固定:变量类型、输入输出、分支循环语法、数组下标、运算符和简单表达式求值。其中百分号、除号、乘号混在一起时,优先级和结合方向必须记得非常熟练,因为这类题在卷子上可以“一眼看到答案”,也能“一眼写错答案”。
我一般会带学生做一组表达式对比,先手算再上机验证。比如计算int c = 5 % 3 + 6 / 2;时,%和/优先级相同,按从左到右结合,先算5 % 3 = 2,再算6 / 2 = 3,结果是 5。看起来简单,但考场上时间紧,学生很容易先算加法。训练方法是每天都做十道“一看就会”的表达式题,但要求把中间步骤写出来:先写乘除模,再写加减,最后写结果。把这个习惯练到肌肉记忆,选择题的基础分就不会丢。
另外,C++ 里带有多个副作用的表达式,例如a++ + ++a,结果可能是编译器相关的“玄学”问题,正规竞赛一般不会出,训练时也不必深究。真正值得记的是数据范围:看到int要想到上限约 21 亿,题目给出更大范围时优先考虑long long。选择题的每一个选项都值得推一遍为什么错,而不是只记正确答案。
2.2 阅读程序题:手写变量变化表,循环边界是重灾区
阅读程序题的困难在于不能运行。孩子一看到循环就心算,循环超过十次必然乱。解决办法是强制在草稿纸上画表:左边写变量名,右边写当前值,每执行一次循环体就更新一次。例如下面这段常见结构:
int sum = 0; for (int i = 1; i <= 5; i++) { if (i % 2 == 0) continue; sum += i; }走查过程是:i=1 时 sum=1;i=2 时遇到 continue,本轮不累加;i=3 时 sum=4;i=4 时继续跳过;i=5 时 sum=9。最终输出 9。很多孩子看到 continue 就以为循环结束,其实它只是跳过当前这一轮,后面的 i++ 照常执行。
读程序题的另一类高频陷阱是循环边界:i <= n与i < n只差一个数。我建议每次读题先把循环范围写出来,例如“i 从 1 到 5,共 5 次”,把范围钉在草稿纸上。养成这个习惯后,遇到嵌套循环也不容易乱。平时做这类题时,不要只对答案,要把“变量变化表”和代码并排写在卷子边上,这一步就是考场上真正的得分动作。
2.3 完善程序题:先圈出变量再填空,顺序比结果重要
完善程序题通常描述一个实际问题,然后给出一段残缺代码,要求补循环条件、累加语句或数组下标。我带孩子用的方法是“三步填空”。第一步,把变量声明和注释读三遍,搞清楚每个变量是计数器还是累加器;第二步,把已给出的代码从头读一遍,用中文在边上写下流程;第三步,看空位前后各一行,推测这一行本来该做什么。
举个例子,求一个正整数 n 的位数,代码骨架大致是这样:
int n, cnt = 0; cin >> n; while (?) { cnt++; ?; } cout << cnt << endl;第一个空是n > 0,第二个空是n /= 10。两个空必须一起理解:cnt 负责数位,n 负责去掉最后一位。只填第一个空会死循环,只填第二个空会少算一位。用 n=123 推一遍:第 1 轮 cnt=1、n=12;第 2 轮 cnt=2、n=1;第 3 轮 cnt=3、n=0;循环结束输出 3。这个手算过程就是标准答案。
完善程序题最忌讳从头到尾找答案,那会导致两个空之间互相矛盾。按流程走,正确率会明显提升。平时训练可以把同一道题做两遍:第一遍在残缺代码上填空;第二遍把完整代码逐行翻译成中文注释,逼自己真正理解,而不是背答案。
2.4 初赛笔答与上机验证:只差一个真实运行结果
初赛是笔答,考场上没有编译工具,但平时训练必须用本地开发环境验证。这里的验证不是为了改答案,而是为了让大脑建立“手算结果”和“实际输出”的对应关系。如果孩子每次手算都错,但上机一跑就懂,说明缺的是走查习惯;如果手算能对但代码写不出来,说明语法还没内化。
我的建议是:日常每一道练习题都按“先笔答、后上机”的顺序来。先写答案,再运行。输出不一致时不要急着改,把运行结果和手算过程并排放,找出是哪一步丢的。这个对比过程就是把黑匣子打开的过程。没有这一步,刷题一百道进步也非常慢。
3. 从具体题目到最小实现:三类高频考点的代码与参数说明
3.1 数字拆位与累加:循环条件的三种写法
数字拆位是初赛完善程序题的最爱,比如“输入一个正整数 n,输出各位数字之和”。最小实现是这样:
#include <iostream> using namespace std; int main() { int n; cin >> n; int sum = 0; while (n > 0) { sum += n % 10; n /= 10; } cout << sum << endl; return 0; }逻辑说明:n % 10取出个位,sum负责累加;n /= 10负责去掉个位。循环条件n > 0是核心,只要 n 不为 0 就继续拆位。参数选择上,如果题目说 n 不超过 10 的 9 次方,int够用;一旦范围到 10 的 18 次方或涉及累乘,就要换成long long。
边界情况也要注意:输入 0 时,循环不进,sum 为 0,这符合“0 的各位数字和是 0”;输入负数时这个写法会输出 0,所以读题时要注意“正整数”三个字。循环体里先取余再整除,顺序不能换;如果先n /= 10,原来的个位就丢了,累加结果必然错。这类小细节就是考场上最容易翻车的地方。
3.2 多重条件判断:从三个数能不能构成三角形说起
初赛的选择题和阅读题都会考 if 的嵌套与逻辑组合,最典型的例子是判断三条边能否构成三角形:
#include <iostream> using namespace std; int main() { int a, b, c; cin >> a >> b >> c; if (a + b > c && a + c > b && b + c > a) { cout << "yes" << endl; } else { cout << "no" << endl; } return 0; }逻辑说明:三角形条件是任意两边之和大于第三边,三个条件必须同时满足,所以用&&连接。注意,这里用int通常够用,因为只是加法比较;但如果题目给的是长整型范围,仍然建议用long long,否则三条很大的边加起来超过 int 上限,结果变成负数,程序反而会错误地输出 yes,这是真实发生过的血泪经验。
训练时可以把三个条件拆开读:以 a、b、c 三条边,先试a + b > c,再试另外两组,然后问孩子“为什么不能只判断最长边小于另外两边之和?”这样能帮助理解分类讨论。完善程序题里这类逻辑通常以挖空形式出现,只要先把条件在草稿纸上写成不等式,再翻译成 C++,就不容易漏。
3.3 数组计数与下标边界:统计频次的三个注意点
统计频次的小题经常出现在初赛和机试衔接阶段,比如“输入 n 个不超过 100 的正整数,统计每个数出现多少次,输出出现次数最多的数”。常见做法是开一个计数数组:
#include <iostream> using namespace std; int main() { int n, x; int cnt[101] = {0}; cin >> n; for (int i = 0; i < n; i++) { cin >> x; if (x >= 1 && x <= 100) cnt[x]++; } int ans = 1; for (int i = 2; i <= 100; i++) { if (cnt[i] > cnt[ans]) ans = i; } cout << ans << endl; return 0; }逻辑说明:cnt[x]表示数字 x 出现的次数,数组下标就是被统计的数字本身。数组开到 101 是因为最大数字是 100,下标从 0 到 100 一共 101 个位置。每次读入 x,直接把对应位置加一,最后扫描一遍找最大值。关键参数有两个:数组长度必须比最大下标至少大 1;找众数时ans初始为 1,保证 i 从 2 开始也能正确比较。
三个注意点:第一,cnt必须初始化,局部数组不初始化时内容不可预测,这是经典翻车现场;第二,如果题目不保证数字范围,就不要用固定数组,先读题再决定开多大;第三,比较时用>还是>=,会影响多个数次数并列时的输出结果,需要在读题时看清“输出最先出现的”还是“输出编号最小的”。代码能跑起来只是第一步,把参数和边界理解透才是备战初赛的真正目标。
4. 备赛时间线怎么排:三个月把初赛准备做成闭环
4.1 第一个月:先过一遍语法清单,不追难题
很多家长一上来就让孩子刷整套试卷,结果孩子连循环都没写熟,读程序题自然读不懂。第一个月只做一件事:把语法清单逐项过一遍,每项配五道小题。清单大致是这个范围:
| 模块 | 内容 | 自测标准 |
|---|---|---|
| 输入输出 | cin/cout 基本用法 | 能读入多个数并原样输出 |
| 变量与类型 | int、long long、char | 能说出什么时候用 long long |
| 分支 | if/else、逻辑运算符 | 能写三段以上嵌套判断 |
| 循环 | for、while、continue、break | 能手动画循环变量变化表 |
| 数组 | 一维数组、下标访问 | 能处理下标从 0 开始的问题 |
| 简单函数 | 返回值和参数 | 能把数字拆位写成函数 |
小学生竞赛的范围通常不要求结构体、指针和 STL 高级用法,所以不必用中学内容吓唬孩子。这个月每天保证 40 分钟,前 20 分钟写代码,后 20 分钟让孩子口头解释“每行是什么意思”。口头解释是效率最高的办法:只要孩子能讲清楚,就说明懂了;讲不清楚,就是还没掌握。
4.2 第二个月:按题型刷,而不是按套卷刷
第二个月进入题型训练。每天安排三类任务:十道选择题、三段阅读程序、两道完善程序。选择题主要练语法和运算符;阅读程序按“画变量表”的方式做;完善程序用三步填空法。这个阶段不要过度关心正确率,而要关心每一步是怎么想的。
做完题之后做一件事:把错题抄在错题本上,只抄关键代码和错因。例如“i <= 5写成i < 5,少了最后一次循环”“cnt数组没初始化,输出随机值”“continue 当成 break,sum 结果少了”。每一条都是一句话。这个阶段积累 30 条以上的一句话说错因,初赛基础题基本就稳了。
4.3 第三个月:模拟卷与时间分配,手速也是分数
第三个月重点做整卷模拟。找一个完整时间段,按初赛的时间长度限时完成。模拟的目的有两个:一是检验知识漏洞,二是训练时间分配。建议的时间分配是:选择题用 20% 的时间,阅读程序用 40%,完善程序用 40%。阅读程序占比高,因为它要手写变量表,最花时间,也最容易因紧张而乱掉。
模拟卷讲评时不要只看正确答案,要复盘每道题的卡点。是读题慢了,还是运算符优先级忘了,还是表格画乱了?把卡点写在同一页边上,下一次模拟前先看上一轮的卡点。这个做法虽然土,但比盲目刷题有效得多。如果临近考试仍然有某类题稳定丢分,就果断放弃钻研偏题,把基础题的正确率保住。竞赛是分数游戏,先保住能拿的分,再谈难题。
5. 初赛高频失分点避坑:五条能直接抄走的踩坑记录
5.1 变量忘记初始化:随机值会让同一段代码“随机”翻车
现象:某同学在完善程序题里写int sum;然后直接累加。第一次运行结果是 5,第二次运行变成 267,第三次又不对。 原因:局部变量未初始化时,sum 的初值是不确定的。不初始化不代表自动是 0。 解决:所有累加器都写成int sum = 0;,计数器写int cnt = 0;,数组用int cnt[101] = {0};。考试时读程序题也要注意:看到int sum;必须继续找有没有赋值语句,没有赋值就直接使用,答案往往是不确定,而不是某个固定数。
5.2 int 溢出:大数算着算着变成负数
现象:某同学在训练时计算 1 连乘到 20,结果输出一个负数。 原因:int 能表示的最大值约 21 亿,20 的阶乘远超这个范围,溢出后结果是未定义的。竞赛里常见数据范围是 10 的 9 次方,加法一般没事,但连乘、平方、累加一旦超过范围就会翻车。 解决:看到“不超过 10 的 9 次方”时先想加法还是乘法;只要可能超过 21 亿,就改用long long。完善程序题里如果空位是cnt++不会溢出;但如果是sum += i * i就要小心。即使出题人没提数据范围,也按保守方式处理,准备读程序题时也先估一下量级,别等结果出错才发现。
5.3 循环边界差一位:i<=n 和 i<n 是两种裁判结果
现象:读程序题问“1 到 100 所有偶数之和”,有学生写成for (int i = 1; i < 100; i++),结果从 1 算到 99,漏掉了 100。 原因:循环边界不清晰,把“小于”和“小于等于”搞混。 解决:每次读循环先写出实际范围,例如“i 从 1 到 99,共 99 次”。完善程序题里填循环条件时,把循环次数算清楚再填:i <= n表示包含 n,i < n表示不含 n,i < n + 1等价于前者。这个排查顺序只有一个字:数边界。
5.4 数组越界:下标从 0 开始,数组长度要加余量
现象:某同学开int a[100];,用for (int i = 1; i <= 100; i++) cin >> a[i];,最后一个数存进a[100],程序有时正常有时崩溃。 原因:C++ 数组下标从 0 开始,a[100]是第 101 个元素,已经越界。越界不一定立刻报错,但可能覆盖其他变量,造成结果时对时错。 解决:需要存 n 个数时,数组长度至少是n + 5,养成多留余量的习惯。计数数组按最大数字范围开:数字最大 100 就开int cnt[101],最大 1000 就开int cnt[1001]。下标使用前,确认它落在 0 到长度减 1 之间。完善程序题里填数组下标时,尤其要看清楚循环变量从 0 还是 1 开始。
5.5 读题漏条件:样例过了,条件丢了
现象:模拟练习时有一题要求“按降序输出所有能被 3 整除的数”,学生把降序看成升序,本地样例跑通,一对答案就错。 原因:竞赛题的条件往往藏在“最多”“至少”“不超过”“按降序”这些词里。一旦漏读,代码再对也没用。 解决:读题时把关键条件圈出来,然后在代码里用注释写一行:// 输出时从大到小。只写代码不写注释,等于没读题。养成这个习惯后,阅读程序题也能更敏锐地注意选项里的限定词。考前模拟卷讲评时,最值得复盘的不是不会做的题,而是会做但条件看错的题,这类分丢得最冤枉。
6. 最后还是要落回机试:用三层验证法检验自己的答案
6.1 本地验证的最小闭环
初赛虽然是笔试,备赛时一定要在本地把每个答案变成可运行程序。最小闭环是:写代码、编译、跑样例、看输出。不要一上来就学复杂调试工具,先用最直接的方式确认“代码说的是不是我想的”。我会让学生在每道题边上留一块草稿区,先写输入和预期输出,再运行代码对比。这一步看似简单,但能把“我以为对了”变成“实际上对了”。
6.2 样例、边界、随机三层验证
验证不能只靠题目给的样例。样例用来解释题意,不是用来保证正确。我自己常用的三层验证是:第一层跑题目样例;第二层跑边界,例如输入 0、1、最大值、最小值和恰好不满足条件的情况;第三层构造几个小随机数据,手工算一遍,再和程序输出对比。第三层最花时间,但对小学生来说很值得练,因为初赛笔答本质上就是手工执行代码的能力。
6.3 把每一道错题压缩成一句后悔药
模拟和日常练习产生的错题,不要整段抄题目。只抄一行关键代码,再写一句原因和一句对策。例如:“while 条件写成n >= 0导致死循环;以后循环里去掉一位时,要在纸上确认 n 什么时候变成 0。”这种一行错因积累三四十条,考前复习效率会非常高。我带学生到最后两周时,只看这几十句话,不再翻整本练习册。
我见过太多孩子把时间花在刷难题上,最后基础题丢分,非常可惜。如果你正在准备下一届,希望这篇梳理直接把你的复习方向带正,希望帮到你。
本文还有配套的精品资源,点击获取