# 2022年第十三届蓝桥杯 Python 大学 B 组真题 > 来源:蓝桥杯官方 & 网络整理 > 总分:150分(2道填空题 + 8道编程题) --- ## 试题A 排列字母(填空题) ### 题目描述 小蓝要把一个字符串中的字母重新排列,使得每个字母都按照字典序排列。 给定字符串:`WHERETHEREISAWILLTHEREISAWAY` ### 解题思路 使用 Python 的 `sorted()` 函数对字符串进行排序。 ### 代码 ```python s = 'WHERETHEREISAWILLTHEREISAWAY' print(''.join(sorted(s))) ``` ### 答案 ``` AAAEEEEEEHHHIIILLRRRSSTTWWWY ``` --- ## 试题B 寻找整数(填空题) ### 题目描述 有一个整数,满足以下条件: - 能被 11 和 17 整除 - 不能被 2 整除(即为奇数) - 满足一系列模运算条件 ### 解题思路 1. 能被 11 和 17 整除 → 能被 187 整除 2. 不能被 2 整除 → 步长为 374(187×2) 3. 找出满足条件的起始数和步长规律 ### 代码 ```python from tqdm import tqdm mod = [(2, 1), (3, 2), (4, 1), (5, 4), (6, 5), (7, 4), (8, 1), (9, 2), (10, 9), (11, 0), (12, 5), (13, 10), (14, 11), (15, 14), (16, 9), (17, 0), (18, 11), (19, 18), (20, 9), (21, 11), (22, 11), (23, 15), (24, 17), (25, 9), (26, 23), (27, 20), (28, 25), (29, 16), (30, 29), (31, 27), (32, 25), (33, 11), (34, 17), (35, 4), (36, 29), (37, 22), (38, 37), (39, 23), (40, 9), (41, 1), (42, 11), (43, 11), (44, 33), (45, 29), (46, 15), (47, 5), (48, 41),(49,46) ] for i in tqdm(range(5458460249, 10 ** 17, 7131746160)): for a, b in mod: if i % a != b: break else: print(i) break ``` ### 答案 ``` 2022040920220409 ``` --- ## 试题C 纸张尺寸 ### 题目描述 纸张尺寸规格: - A0:1189mm × 841mm - A1:841mm × 594mm(A0 对折) - A2:594mm × 420mm(A1 对折) - ...以此类推 输入一个纸张规格(如 A1、A2、A3...),输出其尺寸(长在前,宽在后)。 ### 解题思路 模拟对折过程,每次对折后长宽互换,长度减半。 ### 代码 ```python l = 1189 w = 841 name = input() num = int(name[1:]) for i in range(num): t = l // 2 # 整除 l = w w = t print(l) print(w) ``` --- ## 试题D 数位排序 ### 题目描述 给定两个整数 n 和 m,求 1~n 中所有整数按照数位和从小到大排序后,第 m 个数是多少。 ### 解题思路 1. 计算每个数的数位和 2. 按数位和排序 3. 取第 m 个数 ### 精简代码 ```python n = int(input()) m = int(input()) # 字典解析:key为数,value为数位和 dic = {k: sum([int(i) for i in str(k)]) for k in range(1, n+1)} # 根据字典的值进行排序,取第m个 print(sorted(dic.items(), key=lambda item: item[1])[m-1][0]) ``` ### 详细代码 ```python n = int(input()) m = int(input()) dic = {k: 0 for k in range(1, n+1)} # 创建字典 for num, s in dic.items(): st_list = list(str(num)) # 将数的每一位都分割开来 st_list = [int(i) for i in st_list] # 数据类型转换 dic[num] = sum(st_list) # 求和 dic_lst = sorted(dic.items(), key=lambda item: item[1]) # 根据值进行排序 m = dic_lst[m-1][0] print(m) ``` --- ## 试题E 蜂巢 ### 题目描述 蜂巢结构问题(题目图片暂缺) ### 状态 暂无详细题解 --- ## 试题F 消除游戏 ### 题目描述 给定一个字符串,定义"边缘字符"为: - 该字符与左边字符相同,与右边字符不同 - 或该字符与左边字符不同,与右边字符相同 每次消除所有边缘字符,重复此过程直到没有边缘字符或字符串为空。 ### 解题思路 模拟消除过程,使用标志列表标记需要消除的字符。 ### 代码 ```python st = input() st_list = list(st) # 将字符串转换成列表 for c in range(2**64): # 循环次数 st_flag = [0 for _ in range(len(st_list))] # 生成标志列表 l1 = len(st_list) # 计算字符列表的长度 for i in range(1, len(st_list)-1): if st_list[i] == st_list[i-1] and st_list[i] != st_list[i+1]: # 条件一 st_flag[i] = 1 st_flag[i+1] = 1 if st_list[i] != st_list[i-1] and st_list[i] == st_list[i+1]: # 条件二 st_flag[i] = 1 st_flag[i-1] = 1 st_list2 = [] for i in range(len(st_flag)): # 将边缘字符删去 if st_flag[i] == 0: st_list2.append(st_list[i]) st_list = st_list2 l2 = len(st_list) # 删除后的长度 if l2 == l1: # 长度不变,说明没有边缘字符了 break st = ''.join(st_list) if len(st) == 0: print('EMPTY') else: print(st) ``` --- ## 试题G 全排列的价值 ### 题目描述 求 1~n 的全排列的所有排列的"价值"之和。 定义一个排列的价值:对于排列中第 i 个元素(i 从 1 开始),如果它比前面某个元素大,则价值+1。 ### 解题思路 使用回溯法生成所有全排列,然后计算每个排列的价值。 ### 回溯法代码 ```python n = int(input()) arr = [i for i in range(1, n + 1)] arr_s = [] # 存放全排列后的数组 def permutations(arr, position, end): """生成所有的全排列情况""" if position == end: arr_s.append(arr.copy()) else: for index in range(position, end): arr[index], arr[position] = arr[position], arr[index] permutations(arr, position + 1, end) arr[index], arr[position] = arr[position], arr[index] def list_value(lst): """判断每一个数组里面的价值""" value = 0 for i in range(1, len(lst)): for j in range(i): if lst[i] > lst[j]: value += 1 return value permutations(arr, 0, len(arr)) sum_value = 0 for item in arr_s: sum_value += list_value(item) print(sum_value) ``` ### 内置函数代码 ```python from itertools import permutations n = int(input()) arr = [i for i in range(1, n + 1)] arr_s = list(permutations(arr)) def list_value(lst): value = 0 for i in range(1, len(lst)): for j in range(i): if lst[i] > lst[j]: value += 1 return value sum_value = 0 for item in arr_s: sum_value += list_value(item) print(sum_value) ``` --- ## 试题H 技能升级 ### 题目描述 有 n 个技能,每个技能有初始攻击力 a 和每次升级后减少的数值 b。 总共可以升级 m 次,每次选择当前攻击力最高的技能升级,求最大总攻击力。 ### 解题思路 贪心算法:每次选择当前攻击力最高的技能升级。 ### 代码 ```python import math n, m = map(int, input().split()) a_lst = [] # 存放下次提示攻击力的数值 b_lst = [] # 存放每次加过攻击力需要减少的点数 c_lst = [] # 添加攻击力的次数 for i in range(n): a, b = map(int, input().split()) a_lst.append(a) b_lst.append(b) c = math.ceil(a / b) # 向上取整 c_lst.append(c) s = 0 for i in range(m): max_num = max(a_lst) index = a_lst.index(max_num) if c_lst[index] > 0: s += max_num a_lst[index] = max_num - b_lst[index] c_lst[index] -= 1 print(s) ``` --- ## 试题I 最长不下降子序列 ### 题目描述 给定一个长度为 n 的序列,可以修改最多 k 个元素(修改为任意值),求最长不下降子序列的长度。 ### 解题思路 动态规划 + 贪心: 1. 找出原序列中的最长不下降子序列 2. 考虑间隔 k 个元素后能否拼接更长的序列 ### 代码 ```python n, k = map(int, input().split()) nums = [int(k) for k in input().split()] def funs(lst): """ lst[0:a] 是一个不递减的列表 :param lst: 原列表 :return: lst[0:a]的长度 """ a = 1 for i in range(len(lst) - 1): if lst[i] >= lst[i + 1]: break a += 1 return a left = 0 max_l = 1 while True: lst1 = nums[left:] l1 = funs(lst1) if l1 + left + k >= n: if n - left > max_l: max_l = n - left break if nums[l1 + left] <= nums[l1 + left + k]: lst2 = nums[l1 + left + k:] l2 = funs(nums[l1 + k:]) if l2 + l1 + k > max_l: max_l = l2 + l1 + k else: if l1 + k > max_l: max_l = l1 + k left += 1 print(max_l) ``` --- ## 试题J 最优清零方案 ### 题目描述 给定一个长度为 n 的序列和一个整数 k。 有两种操作: 1. 选择一个元素,减 1 2. 选择一个长度为 k 的连续子序列,全部清零 求将所有元素变为 0 的最小操作次数。 ### 代码(部分) ```python n, k = map(int, input().split()) nums = [int(i) for i in input().split()] left = 0 # ... 后续代码待补充 ``` --- ## 参考资源 - [掘金 - 第十三届蓝桥杯Python大学B组真题详解](https://juejin.cn/post/7162334011053277220) - [CSDN - 2022蓝桥杯PYTHON B组试题](https://blog.csdn.net/soldier76zy/article/details/124065732) - [阿里云开发者社区 - 第十三届蓝桥杯Python大学B组真题详解](https://developer.aliyun.com/article/1058860) --- *文档整理时间:2026-04-09*