news 2026/9/26 6:04:46

2019年CSP-S初赛选择题11-15深度解析:信奥算法核心考点全拆解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
2019年CSP-S初赛选择题11-15深度解析:信奥算法核心考点全拆解

2019年的CSP-S初赛,是很多信奥赛选手又爱又恨的一份卷子。那一年,大家熟悉的“NOIP提高组”换了名字,CSP-S第一次出现在准考证上,C++依然是唯一的指定参赛语言,而选择题第11到第15题,位置正好卡在整张卷子的“腰部”。前面10题还在聊进制转换、逻辑表达式、C++语法这些相对温柔的内容,到了第11题往后,命题人明显开始上强度了——排序、二叉树、二分查找、图遍历、组合概率,全是正经的数据结构与算法分析。这篇文章就把这5道题掰开揉碎,每题从题目还原讲到公式推导,再讲到考场上的快速判断方法,最后附上我这些年刷题带学生总结出来的避坑经验。无论你是第一次准备csp-s初赛的新手,还是刷题遇到瓶颈的进阶选手,这5道题都值得停下来多看几遍。

1. 2019年CSP-S初赛:这套卷子为什么值得反复刷

1.1 那一年,初赛换了张脸

2019年对信息学竞赛圈子来说是特殊的一年。原来的NOIP系列赛事改名为CSP,分为面向入门选手的CSP-J和面向提高组选手的CSP-S,CSP-S第一轮就是大家俗称的“初赛”。虽然名字变了,但考试内核几乎没有变:仍然是笔试,仍然要求选手用C++这门语言所附带的数据结构与算法知识去解题,仍然要过线才能进入第二轮上机考试。

第一轮的满分是100分,题型结构和之前保持一致:一、单项选择题(15题,每题2分,共30分);二、问题求解(2题,共10分);三、阅读程序写结果(4题左右,共约40分);四、完善程序(2题,约20分)。这个结构很有意思:单选虽然只占30分,但它决定了一个人的基本盘。很多选手上机能力很强,可初赛单选因为知识面有漏洞,莫名其妙丢个8到10分,最后就差一两分进不了复赛,这种事每年都有。所以单选的每一道题——尤其是偏算法分析的第11到15题——都不应该凭感觉蒙。

1.2 选择题11-15在整卷中的位置与命题风格

如果你纵向看过近几年csp-s初赛真题,会发现一个规律:选择题前面的1到10题,以语言语法、进制运算、简单数据结构识记为主,属于“送分区”;而从第11题左右开始,命题人开始调转枪口,集中考察经典算法的复杂度分析、树与图的性质推导、组合数学和概率计算。也就是说,第11到第15题是单选部分真正的分水岭,也是不少选手丢分的重灾区。

这几道题的命题风格非常统一:题干不会很长,但每个选项都经过精心设计,干扰项往往来自“记混了的公式”。比如把最坏情况当最好情况、把完全二叉树的节点公式带错、把邻接表的时间复杂度记成O(n²)等等。换句话说,第11到15题考的不是你会不会写代码,而是你能不能把课本里的原理真正理解到位,并且能在考场那种紧张状态下快速作出正确判断。这也是我为什么建议所有准备csp-s初赛复习的人,把2019年这份卷子的这5道题当作“样例题”反复吃透——它们几乎涵盖了初赛单选最核心的几大算法考点。

2. 第11题:冒泡排序的比较次数,最坏情况到底是多少

2.1 题目还原

第11题是一道非常经典的排序算法复杂度题,题目大致是这样的(按常见考场版本整理):

用冒泡排序对n个互不相同的元素进行升序排序,在最坏情况下,算法执行过程中需要进行的元素比较次数为( )。
A. n-1
B. n(n-1)/2
C. nlog2n
D. n²

这道题的正确答案是B。

很多同学看到“最坏情况”四个字,第一反应是“反序嘛,那比较次数不就是n²吗?”然后果断选了D。这个错误太典型了——n²只是数量级上的描述,而题目问的是精确次数,两者不是一回事。冒泡排序的最坏情况比较次数是一个确定的等差数列求和结果,不是n²。

2.2 推导:为什么最坏是n(n-1)/2

要彻底搞清楚这个问题,我们先回忆一下标准冒泡排序的C++实现。不优化的版本长这样:

for (int i = 0; i < n - 1; ++i) { for (int j = 0; j < n - 1 - i; ++j) { if (a[j] > a[j+1]) { swap(a[j], a[j+1]); } } }

外层循环一共跑n-1趟,第1趟时内层j从0到n-2,比较n-1次;第2趟内层j少比较一个,比较n-2次;最后一趟比较1次。把所有趟的比较次数加起来,就是:

(n-1) + (n-2) + ... + 1 = n(n-1)/2。

重点来了:这个次数里,每一趟都会老老实实把相邻元素比较一遍,不管它们是否已经有序。也就是说,在最坏情况下(元素完全反序)比较次数是n(n-1)/2,在最好情况下(元素原本就是升序)比较次数依然是n(n-1)/2——只要用的是上面这种不带任何优化的标准实现。这就是冒泡排序最容易被忽略的性质:它的比较次数在无优化版本下是固定的,与初始数据顺序无关。

至于交换次数,才和数据顺序有关:最坏情况下每比较一次都要交换,交换次数也是n(n-1)/2;最好情况下一次交换都不发生。所以如果题目问的是“最坏情况下交换次数”,答案同样是B;如果问“最好情况下交换次数”,答案是0。

2.3 优化版本:加了flag之后结果会变

说到这里,有经验的选手肯定会想到一种优化写法:在某趟比较中如果一次交换都没有发生,说明数组已经有序,可以直接结束循环。

bool flag = true; for (int i = 0; i < n - 1 && flag; ++i) { flag = false; for (int j = 0; j < n - 1 - i; ++j) { if (a[j] > a[j+1]) { swap(a[j], a[j+1]); flag = true; } } }

加了flag之后,如果初始序列完全有序,第一趟比较n-1次发现没有交换,直接结束,总比较次数就是n-1。这就是为什么网上有些资料会说“冒泡排序最好情况下比较次数是n-1”。两种说法都对,区别在于你讨论的是哪种实现。竞赛初赛命题默认考察的是教材里最标准的无优化版本,所以看到“冒泡排序的最坏比较次数”,选n(n-1)/2准没错。但在复习时,一定要把优化版的逻辑也理解透彻,因为阅读程序题里经常出现带flag的冒泡排序,那时候结论就完全不同了。

2.4 同类变式:选择排序和插入排序也来凑热闹

初赛不会只考冒泡排序,通常会把选择排序、插入排序拿出来做干扰对比。这三个排序的“比较次数”要放在一起记:

  • 选择排序:无论数据顺序如何,比较次数恒为n(n-1)/2;交换次数最多n-1次,最少0次。
  • 插入排序:最好情况下(基本有序)每轮比较1次就插入,总比较次数接近n;最坏情况下(逆序)每轮都要比较到最前面,总比较次数为n(n-1)/2。
  • 冒泡排序(标准版):比较次数恒为n(n-1)/2;交换次数最好0次,最坏n(n-1)/2。

这三兄弟里,选择排序和标准冒泡排序的比较次数完全一样,但交换次数差异很大;插入排序则因为“基本有序时效率极高”这个特性,经常出现在“最好情况复杂度”的考题里。建议复习时自己画一张表,把这几个排序的最坏/最好比较次数、交换次数、稳定性都列出来,考前扫一眼比临时翻书管用得多。

3. 第12题:完全二叉树叶子节点数,两个公式别记混

3.1 题目还原

第12题是一道关于二叉树性质的经典题,题目一般这样表述:

一棵完全二叉树共有1001个节点,则它的叶子节点个数为( )。
A. 500
B. 501
C. 502
D. 无法确定

正确答案是B。

这道题考察的是完全二叉树节点数度的关系,几乎每年csp-s初赛知识点里都会出现类似题目。很多同学看到1001这个数字就开始画图,试图把这个二叉树画出来数叶子,这方向就错了——节点数上千的树画到一半人就崩溃了。这类题要用公式,而不是用蛮力。

3.2 用n0 = n2 + 1推导

在任意二叉树中,设度为0的节点数为n0(也就是叶子节点)、度为1的节点数为n1、度为2的节点数为n2。总节点数满足:

n = n0 + n1 + n2。

同时还有一个经典的边数关系:二叉树中边数等于节点总数减1,也等于n1 + 2n2(每个度为1的节点贡献一条边,每个度为2的节点贡献两条边)。所以:

n0 + n1 + n2 - 1 = n1 + 2n2

化简得到:

n0 = n2 + 1

这个结论对任何二叉树都成立,是二叉树题目的万能钥匙。接下来只需要确定n1的值。完全二叉树有个重要性质:除了最后一层可能不满,其余层都是满的;而且最后一层的节点都连续靠在左侧。这意味着度为1的节点最多只有一个,也就是n1只能等于0或1。

现在把n=1001代入总节点公式:

1001 = n0 + n1 + n2 = (n2 + 1) + n1 + n2 = 2n2 + n1 + 1

如果n1=1,那么2n2=999,n2=499.5,不是整数,矛盾;如果n1=0,那么n2=500,n0=501,恰好成立。所以叶子节点数是501。

3.3 更快的考场判断法

上面这种推导虽然严谨,在考场上还是略慢。我常用的技巧是看节点数的奇偶性。完全二叉树中,当总节点数n为奇数时,度为1的节点数为0,叶子节点数n0 = (n+1)/2;当n为偶数时,度为1的节点数为1,叶子节点数n0 = n/2。

1001是奇数,所以叶子节点数直接就是(1001+1)/2 = 501。这个技巧本质上是上面公式的推论,但快得多。如果题目把1001换成1000,那叶子节点数就是1000/2 = 500。我见过不少同学把这两个公式记反,奇数情况当成n/2、偶数情况当成(n+1)/2,一丢就是2分。强烈建议把“奇加偶减”这个口诀写在笔记本扉页上。

3.4 延伸:与其他树结构考点的联动

初赛不会只考一个孤立的知识点,第12题经常和“满二叉树”“二叉搜索树”等概念绑定出题。比如:一棵高度为h的满二叉树,节点总数是2^h - 1(从第1层开始计数时是2^h - 1,从第0层开始是2^(h+1) - 1,做题前要看清题干定义)。再比如:n个节点的完全二叉树,深度(层数)等于⌊log2 n⌋ + 1,1001个节点的完全二叉树深度就是10,因为2^9 = 512 < 1001 ≤ 1024 = 2^10。

考场上如果遇到“完全二叉树+叶子节点+高度+某层节点数”捆绑出现的题目,我的解题顺序是先确定n1,再求n0,最后用高度公式验证结果是否合理。三步走下来基本不会栽跟头。

4. 第13题:二分查找最多比较几次?判定树说了算

4.1 题目还原

第13题考察的是二分查找(折半查找)的时间复杂度精确值,题目类似:

在长度为1000的有序表中用二分查找法查找一个元素(不论该元素是否存在),最多需要比较的次数为( )。
A. 9
B. 10
C. 11
D. 1000

正确答案是B。

很多同学记得二分查找时间复杂度是O(log2n),于是就想:log2(1000)大约是9.97,取整那就是9啊,选A。但这个想法忽略了两个细节:第一,复杂度是数量级,题目问的是精确比较次数;第二,查找失败的情况也会产生额外的一次比较,最大比较次数应该按判定树的高度来算。

4.2 判定树角度

二分查找的过程可以抽象成一颗判定树:每次把当前查找区间从中间分成两半,中间元素作为根节点,左半区间递归构成左子树,右半区间递归构成右子树。在这棵树上,一次查找就是从树根走到某个节点的路径,路径上经过的节点数就是比较次数。查找成功时走到被找到的节点;查找失败时走到一个空指针的位置,也就是树的外部节点。

所以“最多比较几次”这个问题就变成了“这棵判定树最高有几层”。长度为n的有序表,其二分查找判定树中共有n个内部节点,失败节点有n+1个。对于n=1000,判定树的高度为⌈log2(n+1)⌉ = ⌈log2(1001)⌉。因为2^10 = 1024 > 1001,而2^9 = 512 < 1001,所以需要向上取整个10。

4.3 公式与手算验证

二分查找比较次数有两个常用公式,容易混,这里一起说清楚:

  • 查找成功时,最多比较⌊log2 n⌋ + 1次;
  • 查找失败时,最多比较⌈log2(n+1)⌉次。

n=1000时,成功最多比较⌊log2 1000⌋ + 1 = 9 + 1 = 10次;失败最多比较⌈log2 1001⌉ = 10次。两者一致,答案就是10。

我习惯用一个小例子验证:n=1时,无论成功失败都只比较1次,公式给1;n=2时,判定树一层根节点加一个孩子,最多比较2次,⌊log2 2⌋ + 1 = 2,⌈log2 3⌉ = 2,都对。拿这种极端小数据验证一遍,比死记公式靠谱得多。考场上如果一时忘了公式,直接按n=1、2、3推规律,也能把选项锁定。

4.4 C++实现里的边界坑

二分查找的选择题做对了,上机写代码时还是容易栽,因为边界处理太容易出错。标准写法有很多种,我用的是左闭右闭区间:

int l = 0, r = n - 1; while (l <= r) { int mid = (l + r) / 2; if (a[mid] == target) return mid; else if (a[mid] < target) l = mid + 1; else r = mid - 1; } return -1;

注意这里的mid = (l + r) / 2,当l和r都很大的时候可能存在整数溢出风险,稳妥的写法是mid = l + (r - l) / 2。另外,循环条件是l <= r而不是l < r,后者会导致查找区间缩到单个元素时出错。初赛阅读程序题里经常故意把l < r写出来作为坑,这时候要从“区间是否还需要继续查找”的角度判断,而不是凭对错直觉。

初赛选择题只问“最多比较几次”时,不需要写代码,但理解代码边界能反过来帮你理解判定树的分支逻辑:每次比较后区间减半,直到区间为空才停止,所以判定树的高度本质就是“区间被不断折半直到变空的次数”。

5. 第14题:邻接表存图,DFS为什么是O(n+m)

5.1 题目还原

第14题考察图的基本存储与遍历复杂度,题目大约是:

用邻接表存储一个有n个顶点、m条边的有向图,对该图进行深度优先遍历,算法的时间复杂度为( )。
A. O(n)
B. O(m)
C. O(n+m)
D. O(n×m)

正确答案是C。

这道题的正确率其实很高,但很多人只是记住了“DFS是O(n+m)”,并不知道为什么。初赛一旦换一种问法——比如“用邻接矩阵存储,DFS的时间复杂度是多少”——错误率立刻就上来了。所以这道题一定要从原理上吃透。

5.2 邻接矩阵与邻接表的复杂度对比

先看两种存储结构。邻接矩阵是一个n×n的二维数组,a[i][j]=1表示从顶点i到顶点j有边。在这种结构下,无论图中有多少条边,想要遍历一个顶点的所有出边,都必须扫描一整行n个位置;整个DFS要把每个顶点都访问到,并且每个顶点都要扫描一行,所以总复杂度是O(n²)。这个复杂度只和顶点数有关,和边数m无关。

邻接表则完全不同:每个顶点带一条链表,链表里存的是从这个顶点出发能直接到达的邻居顶点。遍历顶点v的出边时,只需要顺着v的链表走一遍,花费的时间正比于这个顶点的出度。所有顶点的出度之和等于有向图的边数m,所以扫描所有边总共花费O(m)。再加上每个顶点需要O(1)时间打标记、递归调用,n个顶点就是O(n)。两部分合并,总复杂度O(n+m)。

注意一个小小的细节:如果是无向图,每条边在邻接表中会存两次(u的链表里有v,v的链表里有u),所有链表的节点总数是2m。但时间复杂度依然是O(n+m),因为2m和m同阶,常数不影响大O表示。初赛如果问“邻接表中有向图边表节点的个数”,答案是m;问无向图,答案是2m。这两个数字容易混,做题时先确认图是有向还是无向。

5.3 DFS的完整开销拆解

为了把O(n+m)彻底讲明白,我把DFS的递归实现拆成三部分开销:

第一,初始化部分。需要给每个顶点打上“未访问”标记,这是一个长度为n的数组,O(n)。

第二,访问顶点部分。每个顶点最多被调用一次DFS,因为一旦访问就会标记,不会重复进入。n个顶点,每个顶点的进出栈操作是O(1),合计O(n)。

第三,遍历邻接表部分。在顶点v的DFS内部,要循环处理v的所有邻居。循环次数等于v的出度。所有顶点出度之和等于m,所以循环总次数是O(m)。就算某个顶点出度为0,也只是空转一次循环体,不产生额外边开销。

把三部分加起来,O(n) + O(n) + O(m) = O(n+m)。这个推导同样适用于BFS,只是BFS把递归栈换成了队列,本质开销完全相同。所以初赛如果问BFS的复杂度,答案依然是O(n+m)。

5.4 初赛对图遍历的常见考法

图这块内容在csp-s初赛选择题里出镜率很高,除了“DFS/BFS复杂度”之外,还喜欢考这么几件事:

一是“连通分量”。对无向图做一次DFS,能访问到的顶点集合就是其中一个连通分量;如果一次DFS后还有未访问的顶点,说明图不连通。要求“判断一个图是否连通”的标准做法就是做一次DFS或BFS,看是否所有顶点都被访问。

二是“边的方向”。对有向图做DFS,会遇到四种边:树边、反向边、前向边、横向边。初赛不常考这么细,但阅读程序题里可能出现“用DFS统计边的数量”这类变形。

三是“邻接矩阵与邻接表的选择”。如果题目给出一个稀疏图(m远小于n²),用邻接表更省空间且遍历更快;如果是稠密图,邻接矩阵的O(1)判断两点是否相连反而有优势。2019年这道第14题虽然只问复杂度,但后续复习一定要把存储结构的适用场景一起掌握,因为第二轮上机写图论题时,选错存储结构直接决定你能不能拿满分。

6. 第15题:随机取两个数的奇偶和,概率题别硬数

6.1 题目还原

第15题是一道组合计数与概率结合的题,题目类似:

从1到10这10个整数中随机取出两个不同的数,则这两个数之和为偶数的概率为( )。
A. 1/2
B. 4/9
C. 5/9
D. 1/3

正确答案是B。

这道题拿到手,第一反应如果是“直接列出来数”,那就容易数错。10个数取两个一共有45种组合,手工列出45个和再数偶数,不是不行,但考场时间不允许。组合计数题的正确姿势永远是先分类,再套组合数公式。

6.2 组合计数推导

两数之和为偶数,只有两种情况:两个数都是偶数,或者两个数都是奇数。在1到10里,偶数有2、4、6、8、10共5个,奇数有1、3、5、7、9共5个。

取两个不同数的总方案数是从10个里取2个的组合数:

C(10, 2) = 10 × 9 / 2 = 45

两个都是偶数的方案数:C(5, 2) = 10
两个都是奇数的方案数:C(5, 2) = 10
满足和为偶数的方案数总共:10 + 10 = 20

所以概率为20/45 = 4/9。

注意这里不能用“取到两个偶数的概率是1/2 × 1/2 = 1/4,取到两个奇数同理1/4,加起来1/2”来算,因为这是不放回抽取,第一次取到偶数的概率是5/10,第二次再取到偶数的概率变成4/9,连续两次取到偶数的概率是(5/10)×(4/9) = 2/9,两个2/9相加是4/9。这样一算就和组合数完全一致了。

6.3 概率题的通用破题姿势

这5道选择题里,第15题属于“题目最短、思维量最大”的一类。我整理了一套概率题的通用流程,适合csp-s初赛所有概率题:

第一步,确定样本空间。题目说的是“取出两个不同的数”,样本就是组合数C(10,2),不是排列数P(10,2)。区分组合与排列,第一步错了后面全错。

第二步,把事件拆成互斥子事件。“和为偶数”拆成“偶+偶”和“奇+奇”,这两个子事件互斥,概率可以直接相加。

第三步,每个子事件内部用组合数算数量,再除以总数。如果题目偷懒改成“随机放回地取两次”,那样本空间就变成10×10=100个有序对,答案会变成1/2。说明稍微改一个字,结果天差地别,读题时看到“不放回”三个字要格外警觉。

第四步,验证概率范围。算出的概率必须在0到1之间,且所有互斥事件概率之和为1。比如这题“和为奇数”的概率就是1 - 4/9 = 5/9,反过来想也一样:一个奇数一个偶数,共有5×5=25种,25/45=5/9。用两种思路互相验证,答案基本稳了。

6.4 用C++随机数做模拟验证

很多同学复习组合概率时会觉得抽象,我提供一个很实用的自检方法:用C++的随机数模拟跑大量实验,观察频率是否趋近于理论概率。这也是最近csp-s初赛复习群里常有人问“c++随机数怎么用”的典型场景。

#include <bits/stdc++.h> using namespace std; int main() { srand(time(0)); long long cnt = 0, T = 1000000; for (int i = 0; i < T; ++i) { int a = rand() % 10 + 1; int b = rand() % 10 + 1; while (b == a) b = rand() % 10 + 1; if ((a + b) % 2 == 0) ++cnt; } cout << (double)cnt / T << endl; return 0; }

这段代码模拟的是“不放回取两个不同数”的过程,跑100万次实验后输出的结果会在0.444附近波动,也就是4/9的小数形式。如果模拟出来明显偏差,说明题目条件理解反了。这招特别适合验证那种“感觉自己做对了但心里没底”的概率题,比翻答案踏实得多。当然,真上考场还是得靠手算,模拟是课后验证用的。

7. 五个题串起来:初赛选择题的高频考点与应试策略

7.1 考点矩阵:排序、树、查找、图、计数

把这5道题放在一起看,2019年CSP-S初赛选择题第11到15题几乎就是一张“算法基础考点清单”。我整理了一个速查矩阵,准备csp-s初赛复习时可以直接对照自查:

题号核心考点关键公式或结论最容易踩的坑
11冒泡排序标准版比较次数恒为n(n-1)/2把数量级n²当成精确次数
12完全二叉树n0=n2+1;奇数节点n0=(n+1)/2n1取0或1判断错误
13二分查找最多比较⌈log2(n+1)⌉或⌊log2n⌋+1直接取log2(1000)的下整9
14图的DFS邻接表O(n+m),邻接矩阵O(n²)无向图边表节点数是2m
15组合概率不放回抽样用组合数用放回思路导致答案变1/2

这张表浓缩了5道题的全部精华。你会发现它们有一个共同特征:全部都是“公式记忆+逻辑推导”的五五开。公式记不准,推导再快也白搭;推导不会,公式背得再熟也容易用错。所以复习时一定要把两者结合起来,每道题都要能讲清楚“为什么是这个答案”。

7.2 考场时间分配与读题顺序

CSP-S初赛总时长通常是2小时,前面30分的选择题不建议花超过20分钟。我的建议是:前10道语言基础题控制在8分钟内,第11到15题控制在12分钟内,平均每题2分多钟。如果某道题卡了超过3分钟,先圈出来跳过去,把后面问题求解和阅读程序的分拿到再说。

读题顺序上有一点小技巧:做排序、树、图这类算法题时,先看选项再读题干。因为选项里往往藏着“比较次数”还是“交换次数”、“有向图”还是“无向图”、“放回”还是“不放回”这样的关键区分。带着区分点去读题干,能有效避免读完一遍发现没注意细节、又得重读一遍的尴尬。这个习惯我在带学生刷csp-s模拟题时反复强调,实测能省下不少时间。

7.3 近年CSP-S初赛对这几块的调整

翻一翻2020年之后的csp-s初赛真题,会发现命题组并没有抛弃这几类考点,只是换着花样考。2020年前后爱把二分查找放进阅读程序题,让你手算mid的变化过程;2021年左右把二叉树和堆结合,问“插入一个元素后堆的调整次数”;组合概率题则越来越多地结合C++随机数、期望值等概念,题干变得比2019年更绕。但万变不离其宗,底层的公式和推导逻辑,第11到15题里已经全部涉及了。

所以我的结论很明确:2019年这套卷子的选择题第11到15题,就是一份浓缩的“初赛单选高频考点地图”。把它彻底吃透,比盲目刷十套模拟题都管用。

8. 常见问题与避坑速查

8.1 记忆版本不同怎么办

每年考完都有选手在群里争论“第12题到底是1001还是1000”“第15题到底是奇数还是偶数”,主要原因就是不同渠道流传的回忆版题目存在细节差异。应对方法有两个:一是以官方公布的真题为准复习,民间回忆版只用来熟悉题型;二是把同类题的变体都练一遍。比如二叉树节点数,1001和1000的答案差一个,你就把这两个数都算一遍,顺便把999也算一下,这样不管考场碰到哪个数都不慌。我做解析时,题目按常见考场版本整理,个别表述细节可能与原卷略有差异,但核心考点与答案不受影响,复习时重在掌握思路而不是背原题。

8.2 五个高频失分点

结合我这些年的经验,第11到15题的丢分原因高度集中,基本就这五条:

第一,排序题没分清“比较次数”和“交换次数”。比较次数决定了排序算法的效率上界,交换次数才是数据移动的开销。标准冒泡排序最坏比较和交换都是n(n-1)/2,但选择排序最坏比较n(n-1)/2、交换却只有n-1次,两者混在一起必错。

第二,完全二叉树忘了考虑n1的取值。有些同学只知道n0=n2+1,不知道完全二叉树中n1只能是0或1,结果代入公式时随便猜一个n1,答案自然错。记住:先判断节点总数奇偶,再定n1。

第三,二分查找的向上取整和向下取整记反。成功最多比较⌊log2n⌋+1,失败最多比较⌈log2(n+1)⌉,两个公式别混。如果实在记不牢,就用n=1、2、3的小数据现场验证。

第四,图的复杂度没区分存储结构。邻接矩阵O(n²),邻接表O(n+m),这个结论必须刻在脑子里。无向图邻接表的边表节点数2m、有向图m,也是高频陷阱。

第五,概率题没看清“放回”还是“不放回”。一字之差,样本空间从组合变成排列,概率从4/9变成1/2。考场读题时遇到这类字眼可以用笔圈出来。

8.3 速查表:公式加答案汇总

最后放一份浓缩版速查表,考前30分钟翻一遍即可:

考点必背结论
冒泡排序比较次数标准版恒为n(n-1)/2;优化版有序时n-1
完全二叉树叶子节点n为奇数n0=(n+1)/2;n为偶数n0=n/2
二分查找最大比较次数⌈log2(n+1)⌉(失败),⌊log2n⌋+1(成功)
邻接表DFS/BFS复杂度O(n+m);邻接矩阵为O(n²)
无放回取两数和为偶数同奇偶组合数相加 / 总组合数

这5道题对应的答案,我再说一遍:第11题B,第12题B,第13题B,第14题C,第15题B。有意思的是,第11到13题答案都是B,这提醒我们考场对答案分布不要有太多心理暗示——不要因为前面连续选B就怀疑自己做错了,只要推导过程站得住,答案就是对的。

我个人的建议是,刷完这套题后不要急着做下一套,先花10分钟把这5道题的推导过程自己在草稿纸上完整写一遍,再用7.1节的考点矩阵做自测。我在实际教学中发现,能独立写出“为什么选B”的选手,在之后任何一次初赛中遇到同类题,正确率都明显高于只背答案的同学。这种“讲得出道理”的复习方式,才是信奥赛这条路能走远的真正底气。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/26 6:04:28

CommVault 备份 Oracle on Linux:从配置到恢复的完整指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/26 6:04:26

具身智能面试必备:Flow Matching动作生成原理与实战

1. 具身智能面试为什么绕不开Flow Matching这两年具身智能方向的岗位面试&#xff0c;但凡涉及到生成式策略&#xff08;Generative Policy&#xff09;&#xff0c;Flow Matching几乎是一个绕不过去的话题。我从去年开始陆续面了七八家做机器人操作、人形控制、VLA&#xff08…

作者头像 李华
网站建设 2026/9/26 6:03:22

手机浏览器可运行中秋祝福代码

<!DOCTYPE html> <html lang"zh-CN"> <head> <meta charset"UTF-8"> <meta name"viewport" content"widthdevice-width, initial-scale1.0, maximum-scale1.0, user-scalableno"> <title>中秋节快…

作者头像 李华
网站建设 2026/9/26 6:02:29

Substrate区块链开发框架全解析:从核心机制到实战避坑

substrate这个词在不同语境里含义完全不同——做材料的想到基材&#xff0c;做生物实验的想到酶底物&#xff0c;但过去这几年&#xff0c;技术圈里提到substrate&#xff0c;大概率说的是Parity那套区块链开发框架。从个人角度讲&#xff0c;它是我见过最接近"把造链从手…

作者头像 李华
网站建设 2026/9/26 6:02:24

Substrate框架解析:从架构原理到Pallet开发与免分叉升级

打开搜索框输入 substrate&#xff0c;大概率会看到两类完全不同的结果&#xff1a;一类是生物化学里的酶底物&#xff0c;一类是材料科学里的衬底。但如果你是一个写代码的人&#xff0c;最近两年反复刷到的那个 substrate&#xff0c;大概率是另一回事——Parity 团队开源的区…

作者头像 李华
网站建设 2026/9/26 6:01:53

YOLOv8果园果实成熟度检测实战:从环境搭建到模型部署全流程

简介&#xff1a;基于YOLOv8的果树成熟度检测系统是一个可直接运行的毕业设计或课程设计工程包&#xff0c;包含源码、完整数据集、可视化界面和部署教程。项目代码经过实际测试&#xff0c;内置训练、验证和检测闭环流程&#xff0c;启动可视化页面即可操作&#xff0c;并自动…

作者头像 李华