蓝桥杯 in Python 的23 4
start at 2023/01/02.

算法竞赛中常用的是C++,但是C系语言的学习成本略高,时间紧迫还是选择Python好(已经选好了

Python 和 C系、java 的不同点就在于它很方便,由于 Python 是一门解释型语言,所以它的运行就不需要像后两种语言一样先编译再运行,可以直接逐行执行每一条代码,某种意义上讲自带了编译型语言的调试器,用户可以自己在遇到问题时很方便地手动执行代码来检验程序的正确性。Python既可以像计算器一样方便使用者运算,也可以写出程序输入输出

蓝桥杯官方给出的比赛环境是Python 3.8.6,提取码 trvj

按理来说选手可以自己选择用什么编辑器或者IDE(集成开发环境),但也不排除蓝桥杯官方定什么奇葩规则强制要求(上次疫情严重的时候官方提出可以居家考试,有些人就顺势作弊,虽然最后象征性地作废了部分人的成绩),可以只能用python自带的编辑器IDLE写代码,如果不是vim用户(我)那样对触碰远在右下角的上下左右抵触的话,平时使用的工具和 IDLE 差别不大,先介绍一下IDLE的使用方法,以防万一

3.8.6 IDLE の 食用方法

  1. Win10环境下(win11不清楚?)按下windows键,敲IDLE,应该会显示出来,按回车就能打开

image-20230102141733213

我的电脑里装的是3.7和3.11,3.8是无效的的快捷方式(x

image-20230102142023928

idle界面
  1. 默认打开的是Python的终端界面,这里可以和Python交互,但是一般我交互都会在命令行里(黑框框看的舒服),说点用处可能不是很大的点,在 Options 里的 Configure IDLE里面可以调IDLE的外观,我这里只把字体调成了平时用的等间距字体Source Code Pro

image-20230102142730007

​ 除了字体外还能调很多东西,类似高亮颜色之类的,你可以调节到自己舒服为止

image-20230102142855757

  1. 新建文件的方式是左上角的File里的New File,你可以看到同样你可以用快捷键Ctrl + N打开。新建一个文件之后,第一步建议是先按Ctrl + S保存,比赛的时候建议保存到桌面(其实直接放在桌面不是一个很好的选择,因为桌面文件夹是在C盘的,如果电脑出了点问题要重启的话,C盘的数据会被清空?可以在D盘新建一个文件夹,然后在桌面放它的快捷方式),命名成你能认出来是哪题(比如说第一题命名成1.py,另外在写代码的时候也要养成没事按下Ctrl + s的习惯

本地的IDLE貌似出了点问题,我去装一下3.8.6的环境

  1. 3.8.6的IDLE可以显示行号,在编辑界面下的OptionsShow Line Numbers,比原来没行号的看的顺眼一点,再来说一下快捷键吧,Ctrl + z是撤销,Ctrl + shift + z是撤回撤销,Ctrl + s保存,另外常用的Ctrl + a, Ctrl + c, Ctrl + v就不用多说了,F5是执行当前文件(如果你没把刚开始打开的终端关掉,它会在原来的终端上把之前使用过的数据全部清空,按你写的程序运行一遍;如果你关掉了开始的终端,它会新打开一个终端运行)

image-20230102145928138

可以注意到运行完程序之后它已经忘了a=23了,但是它知道asfasf是多少,说明它还拥有程序的记忆

​ 你同样能在上面的Run选项卡找到,Run Module 就是执行当前文件,Python Shell 是打开一个新终端,其他两个我不知道(

  1. 如果你写下一道题的时候想回过头去修改前面的题目,有两种打开方式,第一种是在 编辑器界面 或者 终端界面 点File里的Open...找到对应的文件,然后会新开一个那个文件的编辑器界面(忘记说了,可以写代码的是编辑器界面,有>>> 的是终端界面),第二种方法就是在文件夹里找到那个文件,右键那个文件

image-20230102151452093

​ 点击Edit with IDLE,再点3.8就可以了

  1. 另外一点是不知道你的 spyder 平时用不用括号补全,IDLE是没有括号补全的,如果你用括号补全的话不一定用的习惯,我的习惯是先敲好一对括号然后左移一位,这样可以有点麻烦(vim里不麻烦)但是不会漏括号,你也可以先敲左括号再敲里面的内容再敲右括号,这样敲得按键少了,但是括号很多的时候可能会有漏加了一半括号导致报错的风险

关于IDLE的食用方法就讲到这里吧,下面开始讲点语法

Python语法

Python 程序仅可以使用 Python 自带的库,评测时不会安装其他的扩展库。

OI-Wiki写的python语法 要看一遍,其中NumPy库可以不用看(因为它属于第三方扩展库,程序题里用的话测评机是会报错 0分的,但是如果你做填空题的时候是可以用的,好像Python课已经教过了?反正程序题不要用就行了),看的时候最好自己敲一下,留点肌肉记忆印象,之后忘了可以回去看,每次看都有新发现

我的语法习惯可能不是很好的,仅供参考(经常因为不敲空格被队友吐槽)不要被我带坏了

还有就是因为我平时算法竞赛大多数还是用C++写的,有些Python的内置容器还没掌握(比如优先队列、栈这种),用的熟练一般都是列表、集合、字典,可能是当时蓝桥杯应该还没卷起来,所以捞了个奖,现在大概率是要掌握的,最好参考一下OI-Wiki的容器,我也是第一次知道Python还有这些东西(

个人用Python的习惯

这一小节可能过于个性化,对你没有多大的帮助,推荐跳过

平时写题目的时候一般都用Gvim写Python程序,因为没有用spyder那样的IDE,所以是通过最原始的命令行手动输入命令来执行Python程序,执行方法是python 文件名,很麻烦,但是我貌似对原始的执行方式情有独钟

image-20230102192300280

Python还有交互模式的,小黑框(命令行)我觉得是交互Python的最好环境(这人linux用多了,别信),windows下的方法是Win + R cmd python

image-20230102212103448

如果报错说没有python的话说明电脑的Path里面没有添加Python的路径

输入/输出

我用的输入和输出是最基础的input()print(),用的和OI-Wiki的输入输出差不多

先来讲输入

input()是读入一行输入的字符串,以回车为结束标志

注意是字符串,如果读入的是数字也并不能直接当作数字来处理,要用int()函数把字符串转成整数才能使用,如果是小数记得用float()而不是int()

一般的算法竞赛题目都是像这样的描述:

image-20230102200029382

告诉你接下来有T组,每组可以当作一个独立事件,然后每组一行,有一个数字,一般我会这么写:

T = int(input())
for dasdasd in range(T):
    k=int(input())
    ...

如果第三行的每一行有一个数字改成有5个数字,我会这么写

T = int(input())
for dasdasd in range(T):
    ks=[int(i) for i in input().split()]
    ...

ks[0]是第一个数字,ks[1]是第二个数字,依此类推…

前面说到

input()是读入一行输入的字符串,以回车为结束标志

因为数字都是在同一行,而input会读到回车为止,所以如果输入1 2 3 4 5input()会得到"1 2 3 4 5",我们是无法直接将每个数字分开的,Python课应该学过一个字符串的split()方法,字符串.split('分隔符')会根据分隔符将字符串分成一个数组,而它的默认参数是空格(不给分隔符参数),所以"1 2 3 4 5"经过split()之后就变成了["1", "2", "3", "4", "5"],我们还需要做一步,就是把这个字符串数组变成整数数组,Python课(again)应该也教过这个for嵌套进list的语法,[function(f(i)) for i in xxx],它等价于对xxx里的每个元素都执行一遍function函数,i就是遍历取出来的东西,为什么要写f(i)呢?因为可以不止用i,比如说i * 2,输入一般都是i,然后对每个元素都执行一遍int()就都变成整数了,这个花里胡哨的写法在Python里十分常见,有些题目Python甚至可以直接一行写完(炫技用的)

输入应该这样就够了,下面来说说print

image-20230102203624919

官方帮助里print()有很多参数,我们主要用的参数有sependsep参数用来分词,就是比如说print('1','2',sep=',')会输出1,2,如果为空,就会变成默认的1 2,如果你需要输出12那么你要把sep变成空字符串,print('1','2',sep='')end则是用来在输入的最后加上的字符,默认是\n也就是回车,下面示范一下方便理解

image-20230102204136431

忽视后面那个>>>,那是没有换行的标志

然后算法题里的输出一般都是输出一个数字,你直接print就行,不用管换行,但是如果让你一行输出n个数字用空格噶开,你就要注意了

# 如果没有管换行符
x = [1, 2, 3]
for i in x:
    print(i)
# ->
# 1
# 2
# 3

# 换行符号为空格
for i in x:
    print(i,end=' ')
# 1 2 3 

​ 提交的程序应严格按照输出格式的要求来输出,包括输出空格和换行的要求。如果程序
没有遵循输出格式的要求将被判定为答案错误。请注意,程序在输出的时候多输出了内容也
属于没有遵循输出格式要求的一种,所以在输出的时候请不要输出任何多余的内容,比如调
试输出。

– 来自蓝桥杯官方文档

根据文档,上面的输出方式其实是有风险的,因为3后面是有空格的,有可能会被判格式错误,这里推荐下面这种写法

x = [1, 2, 3]
for i in range(len(x)):
    if i == len(x) - 1 :
        print(x[i])
    else:
        print(x[i], end = " ")

这用到了判断下标,如果是最后一个字符我就不加空格,敲回车,这种写法是最安全的,如果直接遍历列表的话会丢失下标信息,所以一般遍历列表的时候我都是遍历下标的

有用的函数

##把整数的字符串形式转换成整数
int("97") # -> 97

##列表求和,仅限数字数组
sum([1,2,3]) # -> 6

##获取数组长度
len([2,3,3,3]) # -> 4

##排序数组,默认是升序,注意这里是返回一个新的数组
# 不会直接把原来的数组排序,所以可以用一个新的变量来接收排序好的数组
# 也可以直接让原数组变成排序好的数组
a = [4, 2, 1, 3]
a = sorted(a)
print(a) # -> [1, 2, 3, 4]

##也可以降序排序,用reverse参数
b = sorted([1,2,3,4],reverse=True)
print(b) # -> [4, 3, 2, 1]

##数组去重,我都是用list转化成集合再转换回来的
a = [1, 2, 2, 2, 3, 4, 5]
b = list(set(a)) # -> [1, 2, 3, 4, 5]
print(b)

##创建一个1到99的数组
x = [i for i in range(1, 100)]

##创建一个10到0的数组
x = [i for i in range(10, -1, -1)]

##创建一个大小为100000的数组
x = [0] * int(1e5)
# 如果你喜欢下标从1开始,这时候排序和遍历数组的时候要小心点
x = [0] * (int(1e5) + 1)

##创建一个100*100的二维数组
# python里创建二维数组是很麻烦的,不能像上面那样直接乘一个一维数组
x = []
for i in range(100):
    x.append([0] * 100)

## 判断34在不在数组里
if 34 in l:
    print("yes")
else:
    print("no")

# 返回一个字符的ascii码
ord('a') # -> 97

# 返回一个ascii码对应的字符
chr(97) # -> 'a'

3.8 的 math 库里可以用来算组合数的math.comb,相当方便,记得当时我忘了组合数的计算公式了,推了半天,然后dir(math)了一下发现有个comb函数,然后用了一下发现真的是用来算组合数的函数 大喜,印象深刻 🤣

注意点

  • Python的数组其实就是整数的列表

  • Python的range是一个左闭右开区间,range(1,5) 遍历的是[1, 2, 3, 4],第二个参数是永远都取不到的,还有从大到小的时候一定要加上第三个参数range(5, -1, -1),如果是range(5, -1)它会是一个空的,让range只有一个参数的时候,range(x)就会变成range(0,x)

大概就这些了吧,其实你看完了OI-Wiki的,我这些你都不用看了,感觉我还有很多没有讲到 等遇到的时候再说吧

关于算法

关于算法,你需要学习

计算机算法:

枚举排序搜索计数贪心动态规划图论、数论、博弈论、概率
论、计算几何、字符串算法等。

数据结构:

数组、对象/结构、字符串队列、堆、平衡树/线段树、复杂
数据结构、嵌套数据结构等。

– 来自蓝桥杯官方题纲

别怕,数据结构课已经学了一大半了(大概),之前也上过ACM课,只需要深入理解一下就行了,而且很多知识点一般不会来考,来考也只是用来压轴分层次的,拿到暴力分就行了,上面粗体的应该就是学习的重点了(不是很多,嗯

算法除了学习之外还需要大量的做题积累经验,现在不忙的话可以先做找点水题题单来掌握python的输入输出(之前上的ACM课只是有没有忘光?不过应该用的是C语言,两种语言不一样,还是再来一遍吧),顺便接触一下算法竞赛的题目是长什么样的,已经掌握python的算法竞赛形态之后就可以开始学习算法了!

学习方法的话,如果你有自己的学习计划就照自己来(最好给我参考一下,我可能会稍微给点建议),我这里也有之前用过杭电的算法课可以发给你(代码参考是用C++的,我可以帮你翻译成python语言,重要的是算法的思想,或者我来教你(最好不要对我的教学能力抱有期待?(点头

另外这个 OI-Wiki 就是个不错的自学网站,可以花点时间研究一下目录,对知识结构认知有好处,还有它附带Python代码,然后部分知识点看起来可能会有点吃力

每学一个知识点都要做好相关的题单,这样才能理解,然后记得做笔记,做笔记的话我推荐用typora,我还有一个Key可以激活,或者试用一下闲的没事可以像我一样开个博客 写点解题报告(题解报告真的需要很多时间,所以我后面就懒得写题解报告了,但是有助于加深理解)

另外有部分网站还不支持Python做题(点名批评学校OJ),这里推荐点刷题网站,上次那个牛客网就是个不错的刷题网站,还有Vjudge可以刷到各种OJ的题目,但是测评机还是取决于是哪个OJ的题目,所以有些题目不支持交Python,还有洛谷,我之前喜欢在这个网站做题,每道题的几乎都有题解,不会的时候可以去看看,那个题解写的很详细,有问题的时候也可以去提问区问,说不定就有人会来回答你,要用洛谷的话可以帮你找几个题单

理解不了 or 做不出来 or 题解看不懂 可以 来问我(我可能也不会) 或者 去训练的群里问 或者 我帮你问 👍

比赛小技巧(?

虽然现在貌似没有必要看,太唠叨了

先讲一下比赛流程,比赛监考是用桌面录制加上全景摄像头,选手这里不需要去管,赛中不要去百度插U盘这种就好,时间是四个小时,好像是9点开始吧(忘了),覆盖了午餐时间,记得要带水和零食当午饭,到时候肚子饿了就不好了,上洗手间举手和志愿者说一声就可以去了,想上几次上几次(

比赛的时候开机之后先把桌面清理一下,把不用的图标都移到回收站,一般只需要留一个浏览器和试题集,再新建一个Code文件夹之类的用来放代码(怕会遇到重启的情况照上面 食用方法 的 第三点 建快捷方式那样做),一方面是心情舒适,另一方面是防止误触到其他软件多事;另外还要卸载一下电脑里的pycharm,每次运行python文件,它都会自动打开来运行,让人血压有点高,如果能用pycharm你也要用的话就跳过这步(卸载方法:按 win,搜 pycharm,右键搜索结果卸载,然后在新跳出来的程序卸载界面按p检索,双击pycharm之后一路next就能卸载了)

志愿者可能会提供草稿纸,但一般来说他们会忘记拿,要么办公室的纸不够的,最好自己带草稿纸,因为蓝桥杯不能带资料,所以草稿纸最好是干净,没写过东西的那种,当然也要自带笔,推荐再带几张方格纸和铅笔橡皮,有的题目方格纸方便思考一点

比赛的服务器部署在学校内网,网址会写在黑板上(可能是10.xx.xx.xx什么的),那个网页一直开着,交题目也是在那个网页上交的,试题集的压缩包从那个网页上提前下载,但是有密码加密,这个密码只有比赛开始的时候才会写在黑板上,解压出来是pdf文件,这个流程热身赛应该会有,记得参加一下

题型分填空题和程序题,填空题不是计算机二级那种考概念的,是要你计算什么什么的,只需要计算出来然后写上去答案就行了,当然大概率还是需要写代码来求解的(也有部分可以数日历或者手推算出来签到题),题目读清楚再思考,想不出来再读几遍题目,实在不行pass掉随便蒙个答案(填空题也有难的)或者写个暴力求解的程序在后台跑,然后去看其他题(看数据量谨慎行事,有内存爆炸导致死机的风险),然后理论上程序题是难度不按顺序排列的,但是一般前面两三题还是简单的,后面可能不按难度排序,遇到没头绪的题目先放一放之后回头再来看,和高考一个道理(?),不会的题不要空着,蓝桥杯是有小分点的,就是一组输入你给出了正确的输出你就是有分的,所以如果不会或者没头绪要尽量写一下暴力点分,不要忘记提交

写完一道程序题先用样例测试一下,如果给的样例都对了的话可以试着自己手推几组样例再测试一下,还有yes和no的大小写不要搞错,有的会要Yes和No,也有YES和NO

我用python当计算器用喜欢Win + R cmd python 然后开始计算(也不是计算,就是运行想运行的代码,IDLE自带的那个终端运行的时候运算内存会被运行代码覆盖,我也有点用不惯那个界面,不过我这样容易留下很多小黑框,后面嫌窗口多时候要关掉一些的时候会有点麻烦

做完一题或者修改完之后就要去比赛页面上提交代码保存,不要最后出现忘交的情况 要后悔死的

最后 比赛文档 可以读一下,自己记录一些重点

差不多就这样吧,不用全盘接收,这只是我的习惯,参考一下就好,怎么舒服怎么来吧 🥴

加油 (ง •_•)ง

2023/01/03
> CLICK TO back <