2024年第十五届蓝桥杯省赛B组Python题解
一、整体情况说明
2024年第十五届蓝桥杯省赛B组Python组考试共包含8道题目,分为结果填空题和程序设计题两类。
- 考试时间:4小时
- 编程环境:Python 3.x,禁止使用第三方库,仅可使用标准库
- 题型分布:2道结果填空题,6道程序设计题
考试题目涵盖了进制转换、动态规划、模拟、图论、搜索等多个知识点,旨在考察选手的综合编程能力和算法思维。
二、题型分布与分值概览
题号 | 题目名称 | 类型 | 分值 | 涉及知识点 | |
---|---|---|---|---|---|
A | 穿越时空之门 | 结果填空题 | 5 | 进制转换 | |
B | 数字串个数 | 结果填空题 | 5 | 动态规划 | |
C | 连连看 | 程序设计题 | 10 | 模拟、哈希 | |
D | 神奇闹钟 | 程序设计题 | 10 | 模拟、时间处理 | |
E | 蓝桥村的真相 | 程序设计题 | 15 | 模拟、逻辑推理 | |
F | 魔法巡游 | 程序设计题 | 15 | 图论、广度优先搜索 | |
G | 缴纳过路费 | 程序设计题 | 20 | 图论、最短路径算法 | |
H | 纯职业小组 | 程序设计题 | 20 | 图论、拓扑排序 | ([AcWing][1], [博客园][2], [知乎专栏][3], [Dotcpp][4], [力扣 LeetCode][5], [北京语言大学信息科学与技术系][6]) |
三、各题题解与代码实现
题目A:穿越时空之门
题目描述:从1到2024中,找出那些数字,其二进制表示的数位和等于其四进制表示的数位和的数字个数。
解题思路:遍历1到2024的每个数字,分别计算其二进制和四进制表示的数位和,若两者相等,则计数加一。
Python代码实现:
def digit_sum(n, base):"""计算数字n在指定进制下的数位和"""total = 0while n > 0:total += n % basen //= basereturn totaldef count_equal_sums(limit):"""统计在1到limit中,二进制和四进制数位和相等的数字个数"""count = 0for i in range(1, limit + 1):if digit_sum(i, 2) == digit_sum(i, 4):count += 1return countif __name__ == "__main__":result = count_equal_sums(2024)print(result) # 输出结果
结果:63
题目B:数字串个数
题目描述:构造一个长度为10000的数字字符串,要求不含数字0,且必须包含数字3和7,求满足条件的字符串数量,对10^9+7取模。
解题思路:使用动态规划,定义状态dp[i][j][k]表示长度为i的字符串中是否包含数字3(j)和数字7(k)的方案数。
Python代码实现:
def count_strings(length):"""统计满足条件的数字字符串数量"""MOD = 10**9 + 7dp = [[[0]*2 for _ in range(2)] for _ in range(length+1)]dp[0][0][0] = 1 # 初始状态for i in range(1, length + 1):for has3 in range(2):for has7 in range(2):for digit in range(1, 10): # 数字1到9new_has3 = has3 or (digit == 3)new_has7 = has7 or (digit == 7)dp[i][new_has3][new_has7] = (dp[i][new_has3][new_has7] + dp[i-1][has3][has7]) % MODreturn dp[length][1][1]if __name__ == "__main__":result = count_strings(10000)print(result) # 输出结果
结果:157509472
题目C:连连看
题目描述:在一个n×m的矩阵中,统计满足条件的格子对数目。条件是:两个格子中的数字相等,且它们的位置满足|a−c|=|b−d|>0。
解题思路:利用哈希表记录对角线上的数字出现次数,分别处理主对角线和副对角线。对于每条对角线,统计相同数字出现的次数,使用组合数公式计算满足条件的格子对数目。
Python代码实现:
from collections import defaultdictdef count_pairs(matrix):"""统计满足条件的格子对数目"""n = len(matrix)m = len(matrix[0])diag1 = defaultdict(lambda: defaultdict(int))diag2 = defaultdict(lambda: defaultdict(int))for i in range(n):for j in range(m):val = matrix[i][j]diag1[i - j][val] += 1diag2[i + j][val] += 1def count(diag):total = 0for line in diag.values():for count in line.values():if count > 1:total += count * (count - 1) // 2return totalreturn count(diag1) + count(diag2)if __name__ == "__main__":n, m = map(int, input().split())matrix = [list(map(int, input().split())) for _ in range(n)]result = count_pairs(matrix)print(result) # 输出结果
题目D:神奇闹钟
题目描述:给定一个时间字符串,要求将其调整为一个回文时间,且调整后的时间不小于原时间,求最小的调整次数。
解题思路:从原时间开始,每次增加一分钟,直到时间字符串变为回文。
Python代码实现:
def is_palindrome(time_str):"""判断时间字符串是否为回文"""return time_str == time_str[::-1]def next_minute(h, m):"""获取下一分钟的时间"""m += 1if m == 60:m = 0h += 1if h == 24:h = 0return h, mdef format_time(h, m):"""格式化时间为字符串"""return f"{h:02d}{m:02d}"def min_adjustments(h, m):"""计算最小的调整次数"""count = 0while True:time_str = format_time(h, m)if is_palindrome(time_str):return counth, m = next_minute(h, m)count += 1if __name__ == "__main__":time_input = input().strip()h, m = map(int, time_input.split(":"))result = min_adjustments(h, m)print(result) # 输出结果
题目E:蓝桥村的真相
题目描述:在蓝桥村中,n名村民围坐在圆桌旁,每人发表一个声明,称他身后的两人中有一个说真话,一个说假话。求所有可能的真假组合中,说谎者的总数。([CSDN 博客][7])
解题思路:枚举所有可能的真假组合,验证每个组合是否满足所有人的声明,统计说谎者的数量。
Python代码实现:
def total_liars(n):"""计算所有可能的真假组合中,说谎者的总数"""from itertools import producttotal = 0for combo in product([0, 1], repeat=n): # 0表示真话,1表示假话valid = Trueliars = 0for i in range(n):next1 = (i + 1) % nnext2 = (i + 2) % nif combo[i] == 0:# 说真话,后两人中一个真一个假if combo[next1] == combo[next2]:valid = Falsebreakelse:# 说假话,后两人中不是一个真
::contentReference[oaicite:103]{index=103}