☰
C++信息学竞赛校级预选赛单选与程序阅读拆解
2026/10/31 3:40:09 网站建设 项目流程

简介:2024年海淀区中小学生信息学竞赛校级预选赛试题以单份PDF形式呈现,面向准备参加信息学竞赛的中小学生及指导教师,聚焦编程基础知识与程序阅读能力的赛前自测。资源包内共1个PDF文件,约422KB,内容按“编程基础知识单选题”和“程序阅读单选题”两部分组织,题目覆盖变量命名、赋值语句、二进制与十进制转换、表达式运算、逻辑判断、函数定义与调用、循环语句、数组等考点,并配有若干段C++程序供推断输出结果,题型紧凑,便于分模块练习。已有588人学习,适合用于熟悉题型、定位知识薄弱点和教师挑选例题。通过限时练习、错题归类和逐题复盘,读者可系统梳理竞赛基础概念,训练代码阅读与逻辑推理能力,为校级预选赛及后续进阶做好准备。

1. 先看清卷面:校级预选赛的分数,多半丢在“读题”而不是“算法”

2024年某区中小学生信息学竞赛校级预选赛的卷子,最容易让人误判的一点是:它看起来像编程题,实际先用三类单选筛人。第一类是编程基础知识,变量命名、赋值写法、进制转换、表达式结果、数组初始化、循环与函数概念;第二类是程序阅读,给一段 C++ 代码问输出;第三类是问题阅读,用屏幕滚动、视频压缩、掷骰子、爬山记录这类故事包装计数与模拟。想拿分,顺序不是上来就啃长题干,而是先把基础单选和短代码阅读的稳定分收住,再用“变量表+边界值”拆长题。适合刚学完 C++ 语法、能做简单循环和数组、准备校级预选赛的学生;也适合家长帮孩子判断薄弱模块。最容易翻车的地方,是把程序阅读当“凭感觉看代码”,把问题阅读当“数学大题”硬算。实际考的是人肉解释器能力和把故事翻译成变量关系的能力,先把这两件事练顺,分数才会稳。

2. 基础单选:变量、赋值、进制与表达式的送分点怎么拿

2.1 变量命名与赋值语句:先排除“看起来像代码”的选项

变量命名题不考英文水平,考的是 C++ 的硬规则:名字只能由字母、数字、下划线组成,首字符不能是数字,不能是关键字,不能带空格、减号、点号、引号。很多选项故意写成2a、int、a-b、a b这种“像名字但一读就违规”的形式。答题时不要凭印象,按“首字符—字符集—关键字”三步扫一遍,三步都过才是合法变量名。

赋值语句题更容易埋坑。赋值号左边必须是一个可修改的变量,不能是常量、表达式或带引号的字符串;语句末尾要有分号;字符串用双引号,单个字符用单引号。题目里出现5=a;、a+b=3;、"abc";、'a';这类写法,先看左边能不能被赋值,再看引号类型和分号。下面这张表可以直接拿来排查。

检查点合法样子常见错误样子答题动作
首字符a1、_sum1a、$x首字符必须是字母或下划线
关键字scoreint、for对照关键字表排除
特殊符号max_valuea-b、a.b只允许字母、数字、下划线
赋值左边a=3;3=a;、a+b=1;左边必须是变量
引号"abc"、'a''abc'、"a"混用字符串双引号,字符单引号

提示:赋值语句题不要先算右边,先看左边是不是“能装东西的变量”,这一步能排掉一半错误项。

2.2 进制转换与表达式求值:把“符号优先级”写在草稿上

二进制转十进制按权展开:从右往左第 0 位乘 (2^0),第 1 位乘 (2^1),依次相加。遇到1011这种短串,直接写1×8 + 0×4 + 1×2 + 1×1 = 11,比在脑子里跳更快。反过来十进制转二进制用短除法,从下往上读余数。进制题通常不难,错在把权位从左边开始数,或者把2^0当成 0。

表达式求值题考三件事:运算符优先级、整数除法与取余、关系与逻辑运算的结果。算术运算符先乘除后加减,括号最优先;赋值运算符从右往左结合;关系表达式的结果是逻辑值,在 C++ 里通常表现为0或1;逻辑与、逻辑或存在短路求值。字符型变量可以参加算术运算,参与的是字符对应的编码值,不能因为它叫“字符型”就认定不能算。遇到自增自减,先标出变量当前值,再按表达式顺序走,不要跳步。

答题时可以在草稿上写两行:第一行写变量初值,第二行写每一步运算后的值。比如表达式里同时有%、/、*,先把%和/按从左到右结合算清,再算加减。遇到a++和++a,先判断题目问的是表达式值还是变量最终值,这两个问法经常被混在一起。

2.3 分组、排序比较与数组初始化:用枚举和小数据验证

分组题的关键是“人数差不能超过某个值”,不是“每组人数必须相等”。总人数固定、组数固定时,先写出平均分法和余数,再把余数分给不同组,枚举出所有满足差值限制的组合。题目给的具体人数在卷面上,方法不变:设三组人数为 (x,y,z),满足 (x+y+z=N),且任意两组差不超过给定值,逐个枚举 (x) 后检查 (y,z)。这种题最怕凭感觉写一个“平均分”,结果漏掉差值边界。

排序比较次数题先看题目问的是哪种排序。以最简单的冒泡排序或选择排序为例,最坏情况下比较次数通常是 (n(n-1)/2);插入排序最坏也是这个量级。题目给“给定 (n) 个正整数,从小到大排序,最坏需要多少次比较”,先把 (n) 代入公式,再看选项里有没有“正好等于”或“不超过”的表述。若题目问的是“至少”或“最多”,边界会差一次,答题时把 (n=3) 的小例子手算一遍验证。

二维数组初始化题按行优先填。int a[3][2]={2,3,4,5,6,7}的含义是:第一行a[0][0]=2、a[0][1]=3;第二行a[1][0]=4、a[1][1]=5;第三行a[2][0]=6、a[2][1]=7。所以值为 5 的元素是a[1][1]。这类题不要数“第几个”,要写“行号、列号”两个下标,再对照初始化列表的位置。

循环与函数概念题也常放在基础单选里。for可以实现确定次数循环,也可以配合条件实现不确定次数;while同样两种都能做,不能说“while专用于不确定次数”。break跳出整个循环,continue只跳过本次循环剩余部分。函数方面,C++ 程序有且只有一个main函数作为入口;函数可以自己调用自己,这叫递归;C++ 不支持在函数内部再定义函数,但可以在函数内部调用其他函数。题目问“错误说法”时,重点抓“专用于”“必须”“有且只有”这类绝对词,再逐个对照规则。

3. 程序阅读:八道代码题用“变量追踪表”拆开

3.1 先搭拆解框架:输入、初值、循环边界、输出

程序阅读不是让你在脑子里运行完整程序,而是让你当一次“人肉解释器”。拿到代码先做四件事:圈出输入变量,标出所有变量的初值,写清循环的起点、终点和步长,最后锁定输出语句。循环边界是最大的失分点,i<n和i<=n差一次,i=1和i=0差一轮,break出现的位置又会让循环提前结束。下面这张表可以在草稿上直接画。

追踪项要写什么作用
输入变量名、题目给的样例值防止把输入变量和计数器混掉
初值全局变量默认 0,局部变量看定义判断cnt、ans从几开始
循环起点、终点、步长、条件锁定每一轮i的取值
跳转break、continue在哪一行判断是否提前结束或跳过
输出输出哪个变量、有没有换行防止算对过程写错答案

提示:程序阅读先别急着算结果,先把循环变量i的取值列成一行:1,2,3,...,n,再逐个代进去,比盯着代码看稳。

3.2 约数、公因数与最大公因数:三题只差一个终止条件

第一道程序阅读统计的是“小于 (n) 的约数个数”。循环写成for(int i=1;i<n;i++),如果n%i==0就cnt++,注意它没有统计 (n) 本身。输入 6 时,i取 1 到 5,能整除 6 的是 1、2、3,输出 3;输入质数时,只有 1 能整除,输出 1;输入 1 时循环不进,输出 0。答题时先看i<n还是i<=n,再看cnt初值是不是 0,最后按小数据代一遍。

第二道程序统计两个数的公因数个数,但加了“满 6 个就停”。循环从 1 到 (n),条件是两个数都能被i整除就cnt++,每轮结束检查cnt==6就break。因此输出不是公因数总数,而是“公因数总数和 6 的较小值”。答题时先求两个数的最大公因数,再枚举它的因数;如果公因数不足 6 个,输出实际个数,够 6 个就输出 6。不要被m和n的输入顺序绕住,条件里两个取模都要成立。

第三道程序先用min(a,b)找较小值,再从较小值往下找第一个能同时整除a和b的数,这个数就是最大公因数d,最后输出a*b/d,也就是最小公倍数。答题时把“往下找第一个”翻译成“最大公因数”,把最后一行翻译成“最小公倍数公式”,比逐轮手算快。若题目给的是两个具体整数,先写gcd,再算a*b/gcd,注意乘法顺序不要先整除导致精度丢失。

#include <bits/stdc++.h> using namespace std; int gcd(int a, int b) { if (b == 0) return a; // 递归出口:余数为 0 时,a 就是最大公因数 return gcd(b, a % b); // 把 b 和 a%b 交给下一层 } int main() { int x, y; cin >> x >> y; // 输入两个整数 cout << gcd(x, y) << endl; // 输出最大公因数 return 0; }

这段代码对应程序阅读里的递归求最大公因数题。参数a、b是当前两个整数,b==0是终止条件,a%b是余数。阅读时不要展开太多层,记住“大数放前、小数放后,余数接力”,最后非零的那个数就是答案。若题目问的是最小公倍数,还要补一行x / gcd(x,y) * y,先除后乘可以减小中间值。

3.3 回文数、筛法与素数判断:看懂“标记数组”和“提前返回”

回文数程序把整数反转:s=s*10+(t%10); t/=10;,每轮取最后一位接到反转结果后面,最后比较s==x。主程序从 1 到 (n) 逐个调用f(i),统计回文数个数。答题时注意 0 和个位数都是回文数,反转过程中前导 0 会自然消失,不影响比较。若题目给的 (n) 不大,可以直接列小数据验证;若 (n) 很大,就按“逐位反转、相等计数”写思路,不要硬算。

筛法程序先开一个标记数组a,a[1]=1表示 1 不是素数;然后从 2 开始,若a[i]还是 0,就把i的倍数全部标记为 1。后面的循环a[i]=a[i-1]+(1-a[i]);把标记数组改造成前缀和:素数位置贡献 1,合数位置贡献 0,最后a[n]就是 (n) 以内素数个数。答题时先分清“标记数组”和“前缀计数数组”两个阶段,不要把a[i]当成原数。

素数判断程序用for(int i=2;i*i<=x;i++)试除,能整除就返回 0,否则返回 1。主程序先判断n是否素数,是就输出 1;否则若n是偶数输出 2;否则若n-2是素数输出 2;剩下输出 3。这里有个容易忽略的点:试除函数对 1 或 0 可能返回 1,若题目输入包含 1,要单独看边界。答题时先判断n的奇偶,再看n-2,最后落到 3,不要一上来就套公式。

3.4 递归与“找数”题:把函数调用写成栈

递归题的核心是“每一层把问题变小”。以最大公因数为例,f(a,b)在b==0时返回a,否则返回f(b,a%b)。手算时写两列:当前a、当前b,每次把右边的数移到左边,把余数移到右边,直到右边为 0。不要试图在脑子里同时展开多层,写出三层就能看出规律。

“找数”题用while(1)从 2 开始逐个检查,先跳过不是 7 的倍数的数,再统计 2 到 (i-1) 之间能整除 (i) 的个数,等于 6 就记录并跳出。这里的cnt统计的是“真因数个数”,不包括 1 和 (i) 本身;cnt==6意味着总因数个数为 8。答题时先翻译cnt的含义,再按“7 的倍数、真因数 6 个”两个条件同时筛,不要只盯一个条件。若时间紧,先写小范围手算表,通常很快能锁定答案。

4. 问题阅读:长故事题先翻译成“变量、操作、边界”

4.1 屏幕滚动题:位置和编号分开记

屏幕滚动题的文字很长,核心只有三组变量:应用编号、应用所在位置、当前屏幕号。题目说每个屏幕放 (K) 个图标,第 1 到第 (K) 个位置在第一屏,第 (K+1) 到第 (2K) 个在第二屏,以此类推。启动某个应用时,先找它的位置 (p),目标屏幕号是 ((p-1)/K)(从 0 开始数屏幕),从第一屏滚动到目标屏需要“目标屏幕号”次滚动,再双击一次,所以单次操作数是“屏幕号+1”。启动后菜单自动返回第一屏,下一次又从 0 号屏开始算。

变化规则也要单独记:应用启动后,系统把该应用图标与“前一个应用”的图标位置交换。若启动的应用已经在第一个位置,就不交换。这里最容易错的是把“应用编号”当成“位置编号”:应用编号不变,位置会变;前一个应用指的是位置上的前一个,不是编号减一。答题时画一张位置表,每次启动后只更新两个位置,不要重排整个数组。

变量含义更新时机
id应用编号始终不变
pos[id]该应用当前所在位置启动后可能与前一个位置交换
app[pos]该位置上的应用编号与pos同步交换
screen目标屏幕号由(pos[id]-1)/K算出
ans总操作数每次加上screen+1

注意:题目问“完成全部启动需要多少次操作”,要把每次的滚动次数和双击次数都算进去,少加一次双击就会差 (Q)。

4.2 视频压缩题:按时间轴排服务器空闲槽

视频压缩题考的是“多服务器并行+排队”。每个服务器每 (S) 秒压缩 1 分钟视频,同一时间段一个服务器只能压一个视频,同一个视频只能在一个服务器上压。视频按上传时间先后到达,有服务器空闲就立即开始。答题时维护一个“服务器下一次空闲时间”数组,初始全为 0;按上传顺序处理每个视频,选出最早空闲的服务器,开始时间取“该服务器空闲时间”和“视频上传时间”的较大值,完成时间等于开始时间加上“视频长度×S”。

题目里通常会给第 1 个和第 2 个视频长度不同、其余视频长度相同,具体数值在卷面上。不要背数值,记住公式:完成时间 = max(服务器空闲时间, 上传时间) + 长度×S。处理完一个视频后,把该服务器的空闲时间更新为完成时间。最后逐条对照选项,看哪个完成时间说法错误。

步骤动作容易错的地方
1读入服务器数、视频数、压缩速度把“每秒压缩多少”和“每段视频多少分钟”混掉
2按上传顺序排视频打乱顺序会改变排队结果
3找最早空闲服务器只看第一个服务器会漏并行
4算开始、完成时间忘记取 max,视频还没上传就开始压
5更新服务器空闲时间不更新会导致后续全错

4.3 骰子与爬山:可能性判断用“上下界+差值约束”

骰子题给 (M) 个骰子,第 (i) 个骰子有 (a_i) 个面,面上标 1 到 (a_i),同时投掷后和为 (S)。判断“某个骰子上的所有数字是否都可能出现”,不要逐个模拟所有组合,用上下界:固定第 (i) 个骰子的值为 (v),其他骰子的和最小是 (M-1),最大是“其他骰子面数之和”。只要存在 (v) 使 (S-v) 落在这个区间,这个 (v) 就可能;若对 (v) 从 1 到 (a_i) 都成立,才是“所有数字都可能”。答题时先算其他骰子的最小和、最大和,再逐个 (v) 检查区间,不要被“同时投掷”吓住。

爬山题给总天数、第 1 天海拔、第 (D) 天海拔,任意连续两天海拔差不超过给定值,问可能到过的最高海拔。最高点通常出现在中间某天,做法是从左往右推“每天最高可能值”,从右往左推“每天最高可能值”,两边取较小值,再在所有天里取最大。因为左边界和右边界都会限制中间高度,只从一边推会高估。答题时先画一条时间轴,把已知两端标上,再按“每天最多升高多少”向中间夹,最后取夹出来的上界最大值。

5. 易错点:五类一看就会、一选就错的题

5.1 变量名题:把“像单词”当成“合法”

错在哪:看到student、score觉得顺眼就选,忽略选项里可能藏着数字开头、关键字或特殊符号。为什么错:C++ 的变量名规则是硬性的,英文单词再像名字,首字符是数字也不合法;int、for这种关键字更不能当名字。怎么答对:按“首字符—字符集—关键字”三步扫,首字符不是字母或下划线直接划掉,出现减号、点号、空格直接划掉,再对照关键字表。三步都过才留。

5.2 赋值语句题:只看右边算得对不对

错在哪:算出右边表达式的值,觉得没问题就选,没看左边是不是变量。为什么错:赋值号左边必须是可修改的左值,3=a、a+b=1这种写法右边再对也不合法;字符串和字符的引号混用也会报错。怎么答对:先看左边是不是单独一个变量,再看引号类型,最后看分号。左边不是变量,直接判错,不用继续算。

5.3 程序阅读题:忽略i<n和i<=n的边界

错在哪:扫一眼循环,觉得“就是统计约数”,没注意循环终点是<n还是<=n,也没注意break在哪一行。为什么错:少一次循环可能少一个约数,break放的位置不同会让计数提前停止,答案差一整个档。怎么答对:把循环变量取值列出来,标清起点、终点、步长;遇到break画一条竖线,问自己“这一轮后面的语句还执行吗”。小数据代一遍,边界立刻现形。

5.4 函数题:把“递归调用”和“嵌套定义”混为一谈

错在哪:看到“函数可以自己调用自己”觉得对,看到“函数不支持嵌套”又觉得矛盾,结果选错。为什么错:递归是“调用自己”,嵌套定义是“在函数里面再定义一个函数”,C++ 不支持后者,但支持前者;主函数有且只有一个,是程序入口。怎么答对:把“定义”和“调用”分开读,出现“函数里面定义函数”才判嵌套,出现“函数调用自身”就是递归。绝对词“有且只有”“都必须”要逐条对照。

5.5 长题干题:把编号当位置、把上传时间当完成时间

错在哪:屏幕题里拿应用编号直接除以每屏容量,视频题里把上传时间当成完成时间,导致整题方向错。为什么错:应用编号和位置是两个变量,位置会交换;上传时间只是到达时间,完成时间还要加压缩时长和排队等待。怎么答对:长题先画两张表,一张记“编号—位置”,一张记“到达—开始—完成”;每次只更新变化的那一格。题干里的“前一个”“返回第一屏”“同一视频只能一个服务器”都要单独标出来,别用生活经验替代规则。

6. 答题技巧:单选稳分顺序与考前检查清单

这场校级预选赛的单选题,稳分顺序可以固定成三步。第一步先做基础单选里的变量命名、赋值语句、进制转换、数组初始化,这些题短、规则硬,适合开场把手感打热;第二步做程序阅读里代码最短的约数、公因数、回文数题,用变量追踪表逐行代值;第三步再啃长题干的问题阅读,先写变量表,再套操作次数或时间轴公式。最后留几分钟回看绝对词和边界,尤其是i<n、i<=n、break、continue、cnt初值这五个位置。

考前检查可以按下面这张清单走,每项只花十几秒,但能挡住大部分低级失分。

检查项快速动作常见收获
变量名看首字符、关键字、特殊符号排掉数字开头和关键字
赋值语句看左边是不是变量、引号对不对排掉常量赋值和引号混用
进制转换从右往左标权位防止权位从左边数
表达式标优先级、整数除法、短路防止先算加减
程序阅读列循环变量取值、标break防止差一次
函数分“定义”和“调用”防止递归与嵌套混淆
长题干编号与位置分开、到达与完成分开防止整题方向错

押题思路不用铺太宽:基础单选大概率围绕变量、赋值、进制、表达式、数组初始化、循环与函数概念;程序阅读大概率围绕约数个数、公因数、最大公因数与最小公倍数、回文数、筛法、素数判断、递归;问题阅读大概率围绕“位置交换+操作计数”“多服务器排队”“上下界判断可能性”“两端向中间夹”。把这几类各练三道,比盲目刷十套卷更有效。

我以前图快,程序阅读总爱直接看最后一行输出,结果在一道i<n的约数题上少算了一个数,整道题翻车。从那以后我每次模考都强制走一遍“先标变量、再走边界、最后回代”的流程,长题干也先画表再动笔,后悔药少吃了很多。这份试题和配套的拆解笔记我放在资源页,按需取用;希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询