简介第14届蓝桥杯Python省赛真题大学B组PDF文档面向高校软件类竞赛选手尤其是准备蓝桥杯Python组省赛的同学。资料还原了省赛原题与考生须知并配有试题解析覆盖“穿越时空之门”“数字串个数”“连连看”等典型题目其中穿越时空之门涉及二进制与四进制数位和的转换数字串个数需利用组合数学和取模运算避免枚举连连看可通过哈希表快速统计等关键思路。同时文档明确了比赛时长、提交方式、结果填空与程序设计题型的答题要求以及只能使用Python自带模块的编程限制有助于读者熟悉真实的比赛环境。资源包仅含1个PDF文件压缩包大小约228KB体积小巧便于本地离线练习。目前已有1407人学习下载适合赛前冲刺、题型专项突破及备赛复盘使用。1. 第14届蓝桥杯Python省赛大学B组这套题到底在考什么如果你准备打蓝桥杯或者已经在备赛路上被各种算法题折磨过那么第14届Python省赛大学B组的真题是绕不开的一份样本。说实话这套题的难度分布和往年相比有明显调整暴力枚举依然占据半壁江山但字符串处理和模拟题的比例上来了纯数学思维题减少更考验你写代码的熟练度和对Python内置库的掌握。很多人在考场上的翻车点不是思路卡死而是代码写得慢、边界条件处理不干净导致本该拿的分丢了。这篇笔记我直接按真题的考察方向来拆从题型结构、每道题的思考路径到具体的代码实现和 debug 过程都会给到可复现的版本。不管你是第一次参加蓝桥杯还是已经刷过不少题想查漏补缺这篇文章都值得你花半小时读完然后照着敲一遍。2. 真题题型分布与分值逻辑为什么有人感觉“题都会分不高”2.1 近三年题型对比B组在向实际应用靠拢先看第14届省赛大学B组的整体结构。蓝桥杯省赛Python组的题目分为结果填空题和编程大题两大类前者通常有5道后者5道总分150分。和13届相比第14届的填空题减少了对纯数学公式的依赖多了一道“日期处理”和一道“字符串构造”的题这在以前的B组里不太常见。具体来说第14届B组真题的考察点大约覆盖这几个方向等差数列与数论基础、日期与时间处理、DFS深度优先搜索与回溯、字符串排序与哈希统计、二维数组的遍历与状态标记、以及一道压轴的动态规划或贪心题。这种分布意味着你光会“背板子”过时了现在的B组更喜欢看你把Python的列表推导式、字典排序、集合去重这些语言特性用得溜不溜。题号题型核心考点建议用时A填空等差数列 / 数论8分钟B填空日期计算 / 模拟12分钟C填空字符串处理 / 哈希10分钟D填空排列组合 / DFS15分钟E填空二维数组 / 状态枚举10分钟F编程排序 贪心20分钟G编程BFS / 最短路径30分钟H编程动态规划入门30分钟I编程区间合并 / 双指针25分钟J编程综合模拟 / 细节处理30分钟从这个表格能看出来前面的填空题其实是在抢时间。很多人觉得填空题分值小就忽略实际上一道题5分五道就是25分省赛一等奖和二等奖的差距往往就在这25分里。2.2 阅卷规则中的“潜规则”结果对就给分过程没人看蓝桥杯的填空题是“只要最终答案不要过程”的这点和传统OJ题完全不同。每年都有考生在填空题上花大量时间写严谨的推导其实完全没必要。做填空题的正确姿势是大胆用暴力算法、枚举、甚至手工推算怎么快怎么来结果正确就是满分。这里我分享一个实战经验填空题如果数据规模不大直接上Python跑全量枚举不要犹豫。比如日期题一天一天用datetime库循环比手动推日历公式快得多还不会出错。编程大题则相反输出格式和边界条件是阅卷重点样例过了不代表能AC一定要自己构造极端数据测。2.3 省赛分数线参考B组多少分能拿奖根据往年数据第14届B组省赛的获奖分数线大致在一等奖85分左右二等奖65分三等奖50分。要注意蓝桥杯的省赛获奖不设比例上限只要分数够了就能拿对应奖项这和某些竞赛按比例划线不同。所以你的目标很明确前面五道填空全对25分后面五题只要做出两道半到三道基本就有省一。还有一个被很多人忽略的点B组和A组的差距没有想象中大A组只是多了“随机化算法”和“计算几何”两个考点其他题型高度重合。如果你B组的真题刷透了完全可以顺带把A组的填空题拿来练手扩大题库。3. 填空题逐题拆解从暴力枚举到数学优化3.1 第一题等差数列求第n项——两种解法的分水岭这道题在很多人看来是送分题但它实际考察的是你对“等差数列”概念的敏感度以及处理大数的能力。题目大意是给出等差数列的前两项求第n项的值。最直接的解法当然是用公式。但这里有个隐藏坑如果直接用a (n-1) * d来计算当n超过10^7时Python的大整数运算虽然不会溢出但会很慢。我一般建议先判断公差d的正负再决定是否用数学公式。另外要注意输入格式蓝桥杯的输入有时用空格分隔有时换行写代码时最好统一用sys.stdin.read().split()来读。import sys # 读取全部输入按空白字符分割 data sys.stdin.read().split() # 前两个是首项和公差第三个是项数 a, d, n map(int, data[:3]) # 直接用等差数列通项公式Python int无上限 result a (n - 1) * d print(result)这段代码的逻辑很简单但有两个值得说的点。一是用sys.stdin.read()而不是input()是为了防止题目输入最后有多余的换行符导致读入失败。二是map(int, data[:3])这种写法在做真题时能极大减少代码行数考场上的每一分钟都很宝贵。如果你对等差数列的公差求法不熟悉题目如果没有直接给公差记得用a[1] - a[0]来推导。3.2 第二题日期统计——datetime库就是你的后悔药这道题当年坑了不少人。题目要求统计某个时间段内满足特定星期条件的天数。如果用手工推算日历很容易出错如果用datetime库三行代码就解决。这道题也验证了我前面说的填空题不需要“高级算法”只需要“快速且正确”的解法。import datetime start datetime.date(2023, 1, 1) # 起始日期 end datetime.date(2023, 12, 31) # 结束日期 count 0 while start end: # 假设条件是统计星期六和星期日 if start.weekday() 5: count 1 start datetime.timedelta(days1) print(count)这里犯过的新手错误是weekday()返回的是0-6其中0表示星期一6表示星期日。很多人以为返回1-7直接把判断条件写反了。另外datetime.timedelta(days1)的累加操作是生成新的对象所以start必须重新赋值别写成start 1这种错误。这道题本质上考察的是你对Python标准库的熟悉程度。蓝桥杯官方没有规定不能用的库你完全可以把datetime、collections、itertools这些都带上。3.3 第三题字符串的排列组合——哈希表与去重第三题通常是一个字符串处理题比如给一个字符串统计出现次数最多的字符或者判断两个字符串是否互为排列。第14届考的是从一个长字符串中提取满足某种规则的所有子串并统计数量。这种题的核心在于“去重”。如果你用的是list来存结果最后再set()转换在字符串很长的时候会非常慢而且占内存。我一般直接用set来收集结果同时可以配合collections.Counter来做频次统计。from collections import Counter s some_long_string... # 统计每个字符出现次数 counter Counter(s) # 找出出现次数最多的字符 max_char max(counter, keycounter.get) print(max_char, counter[max_char])或者如果是枚举所有长度为k的子串并去重s abcdefg k 3 result_set set() for i in range(len(s) - k 1): result_set.add(s[i:ik]) print(len(result_set))这里需要特别注意的是切片越界问题。range(len(s) - k 1)是标准写法如果你写成range(len(s))在切片时就会得到长度不足k的字符串导致结果错误。这种错误很难通过样例测试发现因为样例数据往往刚好不触发越界条件。3.4 第四题DFS回溯求方案数——模板题的变体DFS题在蓝桥杯里几乎是必考的。第14届这道题大致是在一个棋盘或网格上放置若干棋子满足互不攻击条件求总的方案数。这个知识点属于“怎么考都不意外”的类型。DFS的回溯模板需要熟练到条件反射的程度递归进入→标记状态→递归退出→解除标记。我见过很多同学在考场上因为忘记“解除标记”而直接导致死循环或结果数量爆炸。def dfs(row, n, cols, diag1, diag2): if row n: return 1 # 找到一种合法方案 count 0 for col in range(n): # 判断列、主对角线、副对角线是否有冲突 if col in cols or (row - col) in diag1 or (row col) in diag2: continue cols.add(col) diag1.add(row - col) diag2.add(row col) count dfs(row 1, n, cols, diag1, diag2) # 回溯移除刚才的标记 cols.remove(col) diag1.remove(row - col) diag2.remove(row col) return count n 8 print(dfs(0, n, set(), set(), set()))这个N皇后模板可以用在很多题目里比如格子染色、数独求解等。关键在于对角线的表示方法用row - col和row col来唯一标识两条对角线这样判断冲突的时间复杂度降到O(1)。如果题目数据规模比较大DFS可能会超时这时可以加上记忆化搜索用lru_cache装饰器缓存中间状态。3.5 第五题二维数组的螺旋遍历——模拟题的经典款填空题的最后一题通常是二维数组遍历。第14届考的是“螺旋矩阵”的变体按顺时针方向从外到内遍历一个矩阵输出遍历序列。这道题的难点在于边界处理。我这里给一个非常稳的写法四个方向循环每次走到边界就改变方向。这样写虽然代码长一点但不容易出错。def spiral_order(matrix): if not matrix: return [] res [] top, bottom 0, len(matrix) - 1 left, right 0, len(matrix[0]) - 1 while top bottom and left right: # 从左到右 for i in range(left, right 1): res.append(matrix[top][i]) top 1 # 从上到下 for i in range(top, bottom 1): res.append(matrix[i][right]) right - 1 # 从右到左防止单行 if top bottom: for i in range(right, left - 1, -1): res.append(matrix[bottom][i]) bottom - 1 # 从下到上防止单列 if left right: for i in range(bottom, top - 1, -1): res.append(matrix[i][left]) left 1 return res matrix [[1, 2, 3], [4, 5, 6], [7, 8, 9]] print(spiral_order(matrix))这里有个很容易忽略的问题在“从右到左”和“从下到上”的循环前后必须加上条件判断。因为如果矩阵只有一行或一列经过前两步后top bottom或left right如果不加判断就会重复读取元素。这道题用这个模板可以保证不重不漏。4. 编程大题核心思路从贪心到动态规划4.1 排序贪心区间调度类题目的定式解法编程大题第一题往往是排序加贪心。常见的模型有活动安排选最多不重叠区间、负载均衡使最大值最小、背包变体有限容量下价值最大。第14届考的是“选最多不重叠区间”的变体题目给出每个任务的开始时间和结束时间要求在一段时间内能完成的最多任务数。这个问题的解法思路很固定按结束时间排序然后依次选择开始时间不早于当前结束时间的任务。贪心策略的正确性在于“优先选择结束早的给后面留更多空间”。def max_tasks(tasks): # tasks: [(start1, end1), (start2, end2), ...] tasks.sort(keylambda x: x[1]) # 按结束时间升序 count 0 last_end -1 for start, end in tasks: if start last_end: count 1 last_end end return count tasks [(1, 3), (2, 5), (4, 6), (5, 7)] print(max_tasks(tasks))关键点有两个排序的key是结束时间而不是开始时间这是很多新手会搞反的另一个是判断条件start last_end注意等号能不能取到要看题目条件如果任务在同一时刻结束和开始能衔接就必须用否则用。贪心题在蓝桥杯里的特点是思路不难难在证明和边界。你不需要在代码里写证明但心里要清楚为什么这个选择是最优的。另外如果题目数据规模大到O(n^2)会超时可以尝试用堆heapq来优化每次取结束时间最小的任务。4.2 BFS最短路径模板背熟省赛无忧BFS广度优先搜索是蓝桥杯编程大题的常客考查迷宫最短路径、最少步数达到目标状态等问题。第14届这道题属于经典迷宫问题给定起点和终点矩阵中有障碍物求最短路径长度。BFS的模板必须滚瓜烂熟因为这是确定性最高的拿分点。from collections import deque def bfs_shortest_path(maze, start, end): rows, cols len(maze), len(maze[0]) visited [[False] * cols for _ in range(rows)] # 四个方向上、下、左、右 directions [(-1, 0), (1, 0), (0, -1), (0, 1)] queue deque() queue.append((start[0], start[1], 0)) # (x, y, steps) visited[start[0]][start[1]] True while queue: x, y, steps queue.popleft() if (x, y) end: return steps for dx, dy in directions: nx, ny x dx, y dy if 0 nx rows and 0 ny cols and not visited[nx][ny] and maze[nx][ny] 0: visited[nx][ny] True queue.append((nx, ny, steps 1)) return -1 # 无法到达 maze [ [0, 0, 0, 1], [1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0] ] print(bfs_shortest_path(maze, (0, 0), (3, 3)))BFS的坑主要这几个一是deque要用popleft()如果用列表的pop(0)时间复杂度是O(n)一旦节点多直接TLE二是visited数组必须在入队时标记而不是出队时标记否则同一个节点可能被重复入队造成无限循环三是边界检查必须有有些同学在方向扩展时忘了判断0 nx rows导致数组越界。如果这道题出的不是普通迷宫而是带传送门或钥匙的多状态BFS那就需要把visited数组升级为visited[x][y][state]用三维数组来标记不同状态下的访问情况。这个技巧在处理“带锁的门”这类题目时很关键。4.3 动态规划背包问题的五种变形DP题在省赛B组一般放在编程题的中间位置分值较高。第14届考的是一个“完全背包求方案数”的变体有若干种硬币每种无限个问凑成指定金额有多少种组合方式。这种题比“0-1背包求最大价值”要多想一层因为状态转移方程要改成累加方案数。def coin_change_ways(coins, amount): # dp[i] 表示凑成金额 i 的方案数 dp [0] * (amount 1) dp[0] 1 # 凑成0元有1种方案什么都不选 for coin in coins: for i in range(coin, amount 1): dp[i] dp[i - coin] return dp[amount] coins [1, 2, 5] amount 5 print(coin_change_ways(coins, amount))区分“0-1背包”和“完全背包”的关键就是循环顺序。0-1背包中每个物品只能用一次内层循环要从后往前防止重复计算完全背包每个物品无限用内层循环从前往后。如果搞反了答案就会错得离谱。你可以用一个小数据手动推一遍比如上面的例子dp[5]的结果应该是4即55522152111511111。DP题在蓝桥杯里要想拿全分还需要考虑大数取模。有时候方案数会超过Python的整数安全范围但Python的int是任意精度的所以不太存在溢出问题。不过某些变体题目会要求取模此时dp初始化和转移时都要加% MOD。另外还有一种很常见的变体是“最长递增子序列”LIS这种题一般用二分法优化到O(n log n)而不是朴素的O(n^2)。如果省赛出现建议直接用二分模板。4.4 区间合并与双指针压轴题的低成本保分方案编程大题的最后一道往往最综合压轴题通常是“大模拟”或“区间合并”。这类题的特点是思路不复杂但代码量大、状态多特别考验细心程度。第14届这道题是区间合并的变体给出一组区间合并所有重叠区间输出合并后的区间数。区间合并的标准解法是先排序再线性扫描。注意排序时要同时按起点和终点排序然后根据当前区间的终点来判断是否需要合并。def merge_intervals(intervals): if not intervals: return [] intervals.sort(keylambda x: (x[0], x[1])) # 按起点、终点排序 merged [intervals[0]] for start, end in intervals[1:]: # 如果当前区间起点在上一个区间内部则合并 if start merged[-1][1]: merged[-1][1] max(merged[-1][1], end) else: merged.append([start, end]) return merged intervals [[1, 3], [2, 6], [8, 10], [15, 18]] print(merge_intervals(intervals))这里的排序函数用了lambda x: (x[0], x[1])这是稳妥写法只按起点排序在某些情况下会出错。还有一个容易忽略的点合并时merged[-1][1]要取max而不是直接赋值为当前区间的end。因为可能存在[1, 10]和[2, 4]这样的情况直接赋值会把终点变小。压轴题如果做到这里已经能拿到大部分分了。如果最后的综合模拟题涉及到日期时间、进制转换、字符串解析的多重叠加那就相对耗时。我建议压轴题先跳过把前面有把握的题全部拿下并检查完毕后再回头死磕。5. 蓝桥杯Python组避坑指南来自赛场的血泪经验5.1 输入输出的大坑input()和字节流的抉择蓝桥杯的OJ在读取输入时有时会给出大量数据。如果使用input()函数逐行读取当输入行数达到数千行时input()的缓冲机制可能导致性能下降甚至出现TLE。经验做法是只要输入数据可能超过1000行就统一用sys.stdin.read()来一次性读取。import sys def main(): data sys.stdin.read().split() # 根据第一个数字判断有多少个测试用例 t int(data[0]) idx 1 for _ in range(t): n int(data[idx]); idx 1 arr list(map(int, data[idx:idxn])); idx n # 处理逻辑 print(...) if __name__ __main__: main()这样写看起来繁琐但可以避免很多潜在的格式问题。另外输出也建议用sys.stdout.write()或者把结果放进一个列表最后用\n.join()一次性输出。现在你还在纠结要不要一次性输出等到数据量大时就知道这个习惯能救命。5.2 时间超限不只靠优化更要看数据规模很多同学在准备时只顾着背算法模板却忽视了“看数据规模定算法”这个前提。比如一道题的数据规模是n 10^5你写了一个O(n^2)的排序必然TLE。在考场上有时候你没法立刻想出最优解但可以退而求其次先写一个正确但慢的版本确保能在小数据上拿部分分。蓝桥杯的OJ评测通常会有多个测试点部分测试点数据量小暴力算法能通过这些分也是分不要因为追求最优解而丢掉保底分。据我的经验省赛大题往往有20%的测试点是“白给”的暴力枚举就能过。数据规模可接受的算法复杂度n 10O(n!)n 20O(2^n)n 100O(n^3)n 1000O(n^2)n 10^5O(n log n)n 10^6O(n) 或 O(n log n)记住这张表在考场上拿到题目后先看数据范围再决定采用什么算法。如果能用贪心就不用DP能不用递归就不用递归因为递归的深度过大可能导致栈溢出。Python的默认递归深度在1000左右超过它会直接报错。如果你要用DFS处理深度超过1000的树或图记得加上sys.setrecursionlimit(1000000)。5.3 Python运行速度的“玄学”列表推导式与内置函数蓝桥杯的Python组对时间复杂度要求比C组宽松但这不意味着你可以为所欲为。写代码时养成用内置函数和列表推导式的习惯像是sum()、min()、max()、collections.Counter这些函数底层是C实现的比纯Python循环块几个量级。# 慢手写循环求和 total 0 for num in arr: total num # 快内置函数 total sum(arr)这种微优化看起来不起眼但当数据量达到10^7时差距能到几秒。另外在使用for循环遍历列表时尽量直接遍历元素而不是通过下标访问这样能少一次列表索引查表操作。5.4 大整数与内存Python的隐藏福利与陷阱Python的整数没有位数限制这是一把双刃剑。好处是算大数不需要像C那样手写高精度坏处是无限大整数实际上会消耗更多内存一旦你写出2 ** (n)这种式子且n达到10^7程序会直接内存爆炸。所以在处理这类不需要精确大数的题目时尽量在运算过程中使用取模操作让数值保持在可控范围。另一个常见的隐藏坑是Python的//和math.floor()在负数上结果不一致。例如-3 // 2等于-2因为向下取整而int(-3 / 2)等于-1因为向零取整。在涉及负数下标或分治算法时需要特别注意搞错了很容易造成死循环。5.5 检查代码的通用套路造极端数据很多人在写完代码后只拿样例测试一遍就觉得万事大吉。实际上蓝桥杯的评测数据里有大量边界情况比如长度为1的字符串、只有一行的矩阵、区间完全重叠、输入为0等。我习惯在提交前专门构造这几种极端数据来测试# 极端测试用例 # 1. 空列表 assert function([]) expected_empty # 2. 单元素列表 assert function([1]) expected_single # 3. 全部相同元素 assert function([5, 5, 5, 5]) expected_all_same # 4. 最大数据规模如果时间允许这些断言在本地跑通后代码的鲁棒性会大幅提升。你不需要在提交时带上这些测试代码但养成这个习惯能在考场上救你一命。6. 掌握三个加分技巧让省一离你更近一步6.1 用functools.lru_cache给递归“上发条”在DFS、DP类题目中lru_cache是Python选手的杀手锏。它省去你手动写memo数组的麻烦代码更简洁也不容易出错。只要递归函数是“纯函数”即相同输入必有相同输出就可以放心使用。from functools import lru_cache lru_cache(maxsizeNone) def fib(n): if n 2: return n return fib(n-1) fib(n-2) print(fib(100)) # 秒出结果注意一点lru_cache默认只缓存最近的128次调用结果如果参数空间较大一定要设置maxsizeNone让它无限缓存否则会频繁淘汰缓存导致性能下降。还有一个微不足道但真实的坑被lru_cache装饰的函数其参数必须是可哈希的所以如果参数是列表得先转成元组。6.2 日期题和进制题的快速实现省赛题里日期题的出现频率很高除了14届往年也有类似题目。处理日期时我推荐使用datetime模块不要自己去推算每个月的天数。闰年判断、星期几计算datetime内部都给你封装好了。如果是进制转换题Python的int(s, base)和自定义的转换函数可以秒解。# 任意进制转十进制 num_str ff base 16 decimal int(num_str, base) # 十进制转任意进制支持2-36进制 def to_base(n, base): if n 0: return 0 digits 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ res while n 0: n, rem divmod(n, base) res digits[rem] res return res print(to_base(255, 16)) # FF这段看起来普通的代码里藏着一个细节divmod()一步完成除法和取余比分开写n // base和n % base要快一点且代码更紧凑。如果题目是“负数进制”这种变态考法可以通过加一个偏移量统一处理。6.3 调试习惯二分定位法而不是print大法考场时间紧张很多人遇到输出不对就在代码里到处加print结果越调越乱。我的个人习惯是先确定数据在哪个区间开始出错然后用二分法加print逐步缩小排查范围。比如检查排序后的数组是否符合预期就先打印排序结果的前三个和后三个元素如果大致有序再检查合并逻辑。更省事的方法是在本地用pdb调试器设置断点单步跟踪变量的变化。但考场上可能不熟悉快捷键所以还是推荐在关键节点用print输出中间量。记住调试的时间最好控制在总时间的20%以内超过这个阈值果断放弃这道题去做下一题因为蓝桥杯的评分是按点给分而不是一题定生死。最终回到第14届这套题本身我在复盘时最大的感触是蓝桥杯考的压根不是谁会的算法多而是谁在有限时间里犯的错少。填空题优先暴力拿分大题先写保底解再想优化每道题做完用极端数据自测一遍——这套流程你能在正式比赛稳定执行省一真的不是玄学。希望这些经验和踩坑记录能帮你少走弯路也希望这些题你都能亲手敲一遍真正变成自己的手感。祝你在第15届、第16届的赛场上都能带着这份从容走进考场然后带着满意的分数走出来。本文还有配套的精品资源点击获取 SEO 优化官网定制响应式建站教育培训建站