一、引言
分享Python知识+推广我的Python书。
本号此前陆续分享了2021-2022年全国青少年Python编程挑战赛的题目,已经或将要送娃参加编程比赛或编程培训班的家长朋友可以一下。
关于该比赛的详情,请参考本系列的第1篇推文。
前几次本号分享了该比赛的初中组初赛题目的样题、真题和复赛的全部真题,本次分享决赛阶段的部分题目。
本系列已经发出的推文如下:
《2021-2022年全国青少年Python编程挑战赛题目解析(1)》
《2021-2022年全国青少年Python编程挑战赛题目解析(2)》
《2021-2022年全国青少年Python编程挑战赛题目解析(3)》
《2021-2022年全国青少年Python编程挑战赛题目解析(4)》
《2021-2022年全国青少年Python编程挑战赛题目解析(5)》
在前面分享复赛题压轴题(系列(5))的时候,本号把新手解题的写出来的二十余行程序代码精简成了1行代码,这是算法的威力,真可谓:
编程恒久远,算法永流传。
通过本次分享的决赛题,我们应该能感受到数学知识对算法的决定性作用,真可谓:
算法恒久远,数学永流传。
《Python程序设计(基于计算思维和新文科建设)》,ISBN:9787121435577,胡凤国,电子工业出版社,2022年6月。本书是电子工业出版社在国内较早采用纸质版+电子版的创新图书发行模式的第一次尝试。本书是这套创新图书的纸质版部分,与之内容互补的电子版图书将稍后出版。基础篇介绍Python程序设计的入门知识,共12章,包括:⑶Python的基本概念(对象、数据类型、表达式、内置函数);排错篇总结初学者常遇到的错误并介绍程序调试方法,包含2章:与本书内容互补的电子版图书包含文本篇和应用篇两部分:文本篇:介绍字符集、编码和文本文件读写的知识,包含了对国家规范《通用规范汉字表》8105个汉字当中难以输入和难以显示的汉字的处理。应用篇:介绍Word、Excel、PPT、PDF、图片等常用办公文件的处理,是大家提高办公和科研效率的好帮手。本书配套有详细的PPT和教学大纲,还有全部例题的程序代码和绝大部分思考题的程序代码。本书配套PPT里面还加入了配套电子版图书中的部分内容,比如字符集和编码,不同编码的文本文件的读写,Word、Excel、PPT、PDF等一些常用办公文件的读写。本书对Python基础知识的介绍非常到位,适合中小学生学习Python编程。本书首先介绍了Python的对象、数据类型、变量、运算符、表达式、内置函数等基本概念,介绍输入输出等基本操作,然后介绍程序设计的三大程序结构(顺序、选择、循环)之后,孩子们学完这些就可以做很多有意思的题目,除了很多数学趣题之外,本书还为孩子们准备了海龟画图的知识,这是很多Python比赛常考的内容。在学习完函数和列表、元组、集合、字典、字符串等序列类对象之后,孩子们可以对之前写的程序进行简化和改进,本书遵循了学生学习知识的自然规律,循序渐进地把知识呈现孩子们。本书还贴心地告诉孩子们如何显示文件的扩展名,什么是当前目录等一些常识性的计算机知识,还详详细细地介绍了身份证号的构成规律和辨别真假身份证号这样的科普知识。孩子们通过本书学习Python,不仅仅学到Python编程知识,更可以培养计算思维,对以后学习算法和参加信息学奥林匹克竞赛打下坚实的基础。可以毫不夸张地说,买了本书,可以从小用到大,大学里面学习编程也能用到本书。所以,小编在这里郑重把本书推荐给对编程感兴趣的中小学生,也推荐给已经或打算让娃参加编程比赛或编程辅导班的家长朋友。几千块钱的辅导班费用都舍得,几十块钱一本书是否可以考虑下?您买您娃受益,你不买咱俩都没损失。不过,用心写的书,还是希望能让更多的孩子受益。看本gongzhong号也一样的,也能学到一些Python知识,不过,gongzhong号的更新是不定期的,gongzhong号的介绍不会像书中那么详细、那么系统。可选本书当Python教材或自学Python的参考书。
可拿本书当工具书,本书的配套程序会为您节省效率,在当前大数据和新文科的背景下,本书可以为相关领域的量化研究提供技术支持。可选本书当自学Python的参考书,文科老师写的程序、使用的算法也有可参考之处。
本书配套的电子版图书中的编码和文本处理知识也可以作为理工科教师和科研人员处理文本数据的参考资料之一,毕竟专门开辟章节介绍国家标准《通用规范汉字表》汉字处理的程序设计图书并不多见。本书在各大实体书店和网店均有销售。尤其在电子工业出版社天猫旗舰店销售火爆,月销量100+。京东、天猫、当当的购买渠道如下(可直达购买页面)。(一) 题目:10 道代码编程题,每道题 100 分,满分 1000 分。主网页(ceic.kpcb.org.cn):参赛选手从个人中心的决赛入口进入答题主网页,主网页主要包括三部分:答题入口、答案预览、切换题目。其中答案预览功能已关闭。答题网页:从主网页点击开始答题按钮,会打开新的网页用来答题,代码提交通过之后,关闭答题网页回到主网页,点击下一题按钮切换题目。编程的核心是算法,算法的核心是数学。决赛将更多选用基础的数理逻辑类问题来检验参赛选手的理解问题与解决问题的能力。我们更加鼓励选手深入理解原理与本质,以及灵活运用最基础知识解决实际的数理逻辑问题,而非机械记忆。1. 简单数学运算与Turtle 库:熟悉编程环境,具备编写顺序结构的简单程序的基本编程能力。2. 核心数据类型:列表、元组、字符串、range 类型。4. 算法:解析、枚举、排序、查找,简单的数据处理。5. 具有基本算法思维,具备以算法为目标的编程能力。7. 具有初步的模块思维,函数形式代码复用的编程能力。编程是严谨的过程,应适应所有的场景。为了促进参赛选手
养成良好的思维习惯,比赛系统进行了严谨的答案验证。答题只要提交成功,就说明本题作答完全正确;如果不能成功提交,出现“失败”相关提示,则说明选手需要重新阅读并理
解题意然后修改代码,使之适应所有场景。决赛优先以分数作为选拔标准,如果同分数,则会优先考虑答题时间更短的参赛选手。例如:A 和 B 两位选手分数均为 800 分,A 选手答题总耗时
100 分钟,B 选手答题总耗时 120 分钟,则 A 选手领先 B 选手。示例:任意输入两个正数,编写代码输出两个数字计算的和。测试样例 2:输入 10 和 12.2,输出结果为 22.2测试样例 3:输入 156 和 212.9,输出结果为 368.9登录官网:http://ceic.kpcb.org.cn/,通过决赛入口进入线上答题系统,限时 120 分钟进行答题。考前 30 分钟登录官网:http://ceic.kpcb.org.cn/ ,进入钉钉会议根据监考老师指示进行赛前准备工作。开始线上答题:根据系统页面指引,阅读题目并分别编写代码进行作答,在规定时间内完成比赛并提交。原定于9:00开始比赛,由于系统有些卡顿,部分同学登录和答题有些问题,直到10点才完全正常,原定于11点结束的比赛延长到12点,以弥补选手们因不可抗力造成的时间损失。中午12:00比赛顺利结束。
由于比赛题目有一定难度,比赛下来选手非常劳累,部分题目没有记住,所以本次分享的题目不太全。
小明和小朋友们一起吃苹果,他们一共n个人,每个人至少吃一个苹果,而且每个人吃的苹果数目都不相同。任意输入人数n(n>=1),输出这n个人至少吃多少个苹果
注意:input()内不添加任何参数
只有完全正确才可提交,若无法点击提交说明答题存在错误,可及时进行检查并修改
【输入样例】
3
【输出样例】
6
本题需要先从数学和逻辑上分析吃苹果的总数。因为至少一个,而且每个人互不相同,所以要保证总数最少的话,这n个人吃的苹果数一定是从1开始的连续整数。这样分析之后,我们就容易知道,只需要求出从1连续加到n的和输出就行。

还可以用内置函数sum,前后语句拼接起来一个语句搞定:
缺失。
小明家里有很多不同的趣味书籍,有3个好朋友每人来借一本书(同一本书一次不能借给两个人)任意输入书籍的数量n(3<=n<=100),输出在所有的书籍中,找3本书给3个人有多少种不同的排列组合方法
注意:input()内不添加任何参数
只有完全正确才可提交,若无法点击提交说明答题存在错误,可及时进行检查并修改
【输入样例】
3
【输出样例】
6
这是一道排列组合题,n选3进行排列。如果选手不太了解排列组合的数学知识,可能这道题就不好做。最简单的程序就是输出n、n-1、n-2这三个数的乘积。
如果是熟悉itertools的permutations方法,也可以做出来,先找出n选3的所有无重复排列,再统计这些排列的个数。

不过,第二个做法明显不如第一个,算法技巧固然重要,但不需要用算法就能搞定问题才是最好的算法。而这离不开数学知识,所以学Python的小盆友请记住本次大赛组委会的话:缺失。
缺失。
一个箱子里面存放着50个球,其中10个红色,10个黄色,30个蓝色。现在从箱子里面任意取n个球,计算并输出不同颜色的球的数量组合一共有多少种可能性
注意:input()内不添加任何参数
只有完全正确才可提交,若无法点击提交说明答题存在错误,可及时进行检查并修改
【输入样例】
2
【输出样例】
6
这道题看似一道排列组合题,其实用排列组合来解题的话就复杂了,最简单的就是枚举法,个人感觉本题的考点就是考试范围里面说的枚举算法。

这种优化可以有效减少循环的总次数。不过,在比赛的时候,时间比较紧张,相对于节省程序的运行时间,我们更愿意节省编写程序的时间,这两种程序都是能很快运行出结果的。
如果把问题考虑成排列组合问题,这道题的解法就不那么简单了,首先我们得找出红球、黄球和蓝球数量的所有可能组合,再来看各个组合的三个数字之和是否等于n,最后把等于n的组合数累加起来,才能得到答案。

这段代码要求选手必须对itertools标准库里面的排列组合有关函数比较熟悉,否则,光是自己写生成排列组合结果的程序代码就有很大的工作量。这可能不是本题目的考点。
如果选手对各种算法不太熟悉,枚举各种可能就是唯一的办法,枚举法可以说是算不上算法的算法,枚举几乎是我们人类思考问题的本能选择和首要选择。在程序设计中,枚举法可以用循环(必要时使用多重循环)来实现,解决著名的百钱百鸡问题就是枚举法的一种典型应用。附:【百钱百鸡问题】公鸡五块钱一只,母鸡三块钱一只,小鸡一块钱三只,要求用一百块钱恰好买一百只鸡,而且三种鸡都要买,请输出所有的买鸡的方案。
对于本题,也是非常适合用枚举法的,红球可以选0到10个,黄球可以选0到10个,蓝球可以选0到30个,我们设一个三重循环就可以枚举红球、黄球、蓝球的所有数量组合,挨个考察每个组合的总数是否等于n就行了。
缺失。
当数字的位数高达上百位时,这样庞大的数字在计算机中的计算已经完全不能用简单的加减乘除来实现了,但是有时候对于这种高精度数字的处理也是编程中必不可缺的。任意输入一个数字n(99999<n<999999),计算n的n次方(即连续n个n相乘)计算之后,最后的3位数字是多少 只有完全正确才可提交,若无法点击提交说明答题存在错误,可及时进行检查并修改
这道题考的是基础知识:Python支持任意大的整数(只要内存能存储得下),所以n个n相乘直接用n**n就行,取后三位不就是除以1000取余嘛?所以,这个程序应该很好写出来。
如果担心判卷程序输出的n过大导致程序运行失败,可以考虑每次相乘之后只保留乘积的最后三位(因为我们只关心结果的最后三位,所以可以从数学上证明中间结果只保留最后三位跟保留全部数位的最终结果是一样的),这又是考数学知识啊。

n选3进行排列。如果选手不太了解排列组合的数学知识,可能这道题就不好做。
一群渔民被海盗抓住了,依次坐在编号为1~n的凳子上,其中有一个人身上有藏宝图。现在海盗想要找那个身上带着宝藏的渔民,海盗先将1号凳子上面的人搜身,没找到就隔1个凳子,将3号凳子上面的人搜身,没找到就隔2个凳子,将6号凳子上面的人搜身。以后每次多隔一个凳子去搜索这样下去找了100次没找到,最终放弃了把渔民释放了。任意输入一个数字n(5<=n<=20)代表渔民的数量,依次输出哪些编号的渔民不会被搜身 只有完全正确才可提交,若无法点击提交说明答题存在错误,可及时进行检查并修改
这道题其实说得有点含糊,应该是围成一圈依次坐在1~n的凳子上,如果不围成一圈坐,这道题是没法做的。这道题跟程序设计中的“约瑟夫问题”很像,都是把人安排成一围再数数,所不同的是,约瑟夫问题中的数数间隔是固定的,而且圈中的人是不断减少的,本题目的数数间隔逐渐变大,而且圈内的人数始终是不变的。附:【约瑟夫问题】有一件礼物,要送给如下游戏的幸运者:有n(n>1)个人(编号分别为1、2、…、n)按编号从小到大的顺序按顺时针方向围成一圈。要求从编号为1的人开始顺时针方向轮流报数,第一个人报1,第2个人报2,……,报到m(m>=1)的人退出圈子,然后从退出者的下一位开始从1重新报数,报到m的人退出圈子......直到最后一个人退出圈子,最后那个人即为幸运者,该幸运者将得到那份礼物。既然都是围成圈数数,那么,少不了的一个知识点就是整除取余。因为是围成了圈,所以第n号椅子的下一个位置肯定是第1号椅子,所以每个椅子往后数数的结果如果超过n,是要从1继续数数的。知道了这一点,程序就不难写了,当然,对于初中的小盆友来说,还是有一定难度的。
突然想到,20年前在传大给本科生上C语言课的时候,讲义里面有一道狐狸抓兔子的问题,活脱脱就是本题海盗和渔民的翻版:

20年了,很多东西如过眼烟云,但这道编程题目居然还没有过时。
【题目背景】
学校举办亲子运动会,所有的父亲一组,孩子一组,出场规则是:父亲组先派一个人上场之后孩子组才能派一个人上场,假设每队3个人,可能的出场策略包括5种:父父父子子子
父父子子父子
父父子父子子
父子父父子子
父子父子父子
任意输入父子的对数n(3<=n<=15),计算并输出有多少种出场策略 只有完全正确才可提交,若无法点击提交说明答题存在错误,可及时进行检查并修改
这道压轴题把不少小盆友难住了,小编一开始也不得要领题,眼泪汪汪的小神兽一看老爹也不会,就不太难过了,小编借口忙工作,把小神兽支开,然后打开IDLE开启编程模式,终于想出来三种算法。全排列、去重、检验,检验的办法是:在任何时刻,只要场上的儿子数目大于父亲的数目,这个出场序列就不符合出场策略。比如:自己写全排列代码比较费劲,我们还是使用itertools标准库的permutations对象。

理论上,这段代码是正确的,但实际运行的时候时间效率太差。对于输入的n值小于等于6的时候,它能很快出结果,n等于7的时候,居然要几十分钟才能出结果,n等于8干脆就没敢做实验。题目说了,输入的n小于等于15,n=7时的运行时间就已经不可接受,可见,上面的代码是不能通过实时评分系统批改的。
为此更改算法,不把它看成排列问题,把它看成组合问题,这就是算法二。我们设想有 2*n 个盒子从左到右排成一排,第一个盒子投入了“父”这个字,其它的2*n-1个位置,再选出n-1个位置投入“父”字,其它位置自然是留给“子”这个字的。于是,问题转变成2*n-1选n-1有多少种选法。当然,有些选法是不对的,例如:除了第一个盒子是“父”字,其它的“父”字都在最后n-1个盒子里。
不过,这比算法一好了很多,因为算法一是从2n的阶乘种可能出场顺序中选择合适的出厂策略,而算法二只需要从2*n-1选n-1的选法结果中再来筛选,工作量要小很多。

搞出算法二之后,心里美滋滋的,不过想到初中的小朋友们很难掌握排列组合的代码,就又深入想了一下,居然发现了一个简单的方法:分治法。
分治法是本次比赛的考点之一,但我们很难想到如何用分治法解决本题目,居然被小编想到了,先嘚瑟一下。
设想有一个元组(n, n),表示尚未上场的父亲数目和儿子数目。在任何一个时刻,如果元组的第一个元素为0,则表示未上场的父亲的数目为0,表示父亲全都上场了,剩下未上场的孩子都可以上场,此时对应一种合理的出场策略。在任何一个时刻,如果元组的第一个元素大于第二个元素,说明场上的儿子数目大于父亲数目,则说明不是一个合理的出场策略。其他时候,我们派父亲上场也可以,派儿子上场也可以,后续都有可能对应一些合理的出场策略。
这个程序速度比算法二的程序还要快。当n很大的时候,它也会很慢,但比赛题目规定了n最大是15,速度方面我们无需担心。通过解析本次比赛的真题,我们会发现,大赛组委会说的非常在理:编程的核心是算法,算法的核心是数学。希望小朋友们从Python编程开始,逐步喜欢上算法,喜欢上数学。如果需要跟图书《Python程序设计(基于计算思维和新文科建设)》的作者胡凤国老师进行交流,请发电邮:cuchufengguo@163.com,也可以给gongzhong号留言进行交流。欢迎gongzhong号“语和言”,本gongzhong号将不定期发布对本书Python知识点的解读文章,也会补充书中未曾收录的一些内容。
语和言gongzhong号还有读者交流群,本书读者可以入群一起讨论问题,如果您的娃在学习本书的过程中有什么问题,我们可以在群里交流。