天梯赛真题 Python 题解合集
目录
- [L1-1 一行代码](#L1-1 一行代码)
- [L1-2 要刷多少题](#L1-2 要刷多少题)
- [L1-3 就挺突然的](#L1-3 就挺突然的)
- [L1-4 普及赛排名](#L1-4 普及赛排名)
- [L1-5 做什么都被骂怎么办](#L1-5 做什么都被骂怎么办)
- [L1-6 钓鱼佬专用挪车电话](#L1-6 钓鱼佬专用挪车电话)
- [L1-7 网络流量监测](#L1-7 网络流量监测)
- [L1-8 智慧文本编辑器](#L1-8 智慧文本编辑器)
- [L2-1 姥姥改作业](#L2-1 姥姥改作业)
- [L2-2 超参数搜索](#L2-2 超参数搜索)
- [L2-3 森林藏宝图](#L2-3 森林藏宝图)
- [L2-4 大语言模型的推理](#L2-4 大语言模型的推理)
L1-1 一行代码
题意
签到(请输出文本)
代码
python
print("Building the Future, One Line of Code at a Time.")
关键点标注
- 签到题:直接输出给定字符串
L1-2 要刷多少题
题意
输出 15 × n
代码
python
n = int(input())
print(n * 15)
关键点标注
- 简单计算 :输入一个整数
n,输出15 × n
L1-3 就挺突然的
题意
给定两个年份A和B,先计算B - A输出,再根据其是否> 250、≤ 0、≤ 250或在1 ~ 250之间分别输出对应提示语。
代码
python
def solve():
a, b = map(int, input().split())
d = b - a
print(d)
if d <= 0:
print("hai sheng ma?")
elif d <= 250:
print("nin tai cong ming le!")
else:
print("jiu ting tu ran de...")
solve()
关键点标注
- 条件判断 :
d ≤ 0、d ≤ 250、d > 250三个区间分别输出不同提示语 - 翻译 :
hai sheng ma?(还生吗?)nin tai cong ming le!(您太聪明了!)jiu ting tu ran de...(就挺突然的...)
L1-4 普及赛排名
题意
给定n个数,统计里面< 1700的数的个数。
代码
python
n = int(input())
cnt = 0
for _ in range(n):
a = int(input())
if a < 1700:
cnt += 1
print(cnt)
关键点标注
- 计数:遍历输入,统计小于1700的数的个数
L1-5 做什么都被骂怎么办
题意
给定n条记录,每条记录包含两个值:编号x和被评价类型y(y=0表示被骂,y≠0表示被夸)。
找出只有被骂而没有被夸的人,按编号升序输出;没有就输出NONE。
思路
用两个标记数组分别记录每个编号是否被骂过、是否被夸过,最后按编号升序输出"被骂过且从未被夸过"的人。
代码
python
def solve():
n = int(input())
# 标记数组:a记录是否被骂,b记录是否被夸
# 编号范围1~100000,用数组模拟哈希
a = [0] * 100001 # 是否被骂过
b = [0] * 100001 # 是否被夸过
for _ in range(n):
x, y = map(int, input().split())
if y == 0:
a[x] = 1 # 被骂标记
else:
b[x] = 1 # 被夸标记
result = []
for i in range(1, 100001):
if a[i] and not b[i]: # 被骂过且没被夸过
result.append(i)
if not result:
print("NONE")
return
print(' '.join(map(str, result)))
solve()
关键点标注
- 双标记数组 :
a[i]记录是否被骂,b[i]记录是否被夸 - 筛选条件 :
a[i] and not b[i]被骂过且没被夸 - 编号范围:注意编号可能达到100000,数组开100001
L1-6 钓鱼佬专用挪车电话
题意
给定11行分别由0 ~ 9个m构成的字符串,最后输出每行m的个数。
思路
通过getline(cin, s)输入每行字符串,输出s.size()返回的值。
代码
python
def solve():
a = []
for _ in range(11):
s = input().strip() # 读取每行字符串
a.append(len(s)) # 记录长度
# 输出每行长度
for i in a:
print(i, end=' ')
solve()
关键点标注
- 输入处理 :共11行固定输入,每行由
0~9和m组成 - 长度统计 :
len(s)或s.size()返回字符个数
L1-7 网络流量监测
题意
给定n个每小时流量值,输出最大值、最小值和平均值(向下取整),再找出所有流量严格大于平均值2倍的点(没有则输出Normal)。
思路
先一次遍历求出最大值、最小值和平均值(整除向下取整),再二次遍历找出所有流量严格大于平均值2倍的下标输出,否则输出Normal。
代码
python
def solve():
n = int(input())
a = [0] * (n + 1) # 1-indexed,a[0]不用
s = 0 # 总和
mx = 0 # 最大值
mn = float('inf') # 最小值,初始化为无穷大
for i in range(1, n + 1):
a[i] = int(input())
s += a[i]
mx = max(mx, a[i])
mn = min(mn, a[i])
avg = s // n # 平均值向下取整
print(mx, mn, avg)
# 找严格大于平均值2倍的点
result = []
for i in range(1, n + 1):
if a[i] > avg * 2: # 严格大于,不是大于等于
result.append(i)
if not result:
print("Normal")
return
print(' '.join(map(str, result)))
solve()
关键点标注
- 平均值计算 :
s // n实现整数除法向下取整 - 严格大于 :
a[i] > avg * 2注意不是>= - 最小值初始化 :
mn = float('inf')确保任何输入都能更新
以上就是全部十一道天梯赛真题(L1-1 ~ L2-4)的 Python 题解,你可以直接复制发布到 CSDN。
如果需要进一步加注释说明或者测试数据解释,告诉我!
L1-8 智慧文本编辑器
题意
模拟一个支持三种操作的(查找子串前 3 次出现位置、插入字符串、翻转指定区间字符串)的文本编辑器,按输入指令处理字符串并输出对应结果
思路
暴力模拟即可
代码
python
def solve():
t = input().strip() # 初始字符串
n = int(input()) # 操作次数
for _ in range(n):
op = input().split() # 读取操作
x = int(op[0]) # 操作类型
if x == 1:
# 操作1:查找子串前3次出现位置
a = op[1] # 子串
pos = []
for j in range(len(t)0 - len(a) + 1): # 枚举所有可能的起始位置
match = True
for k in range(len(a)):
if j + k >= len(t) or t[j + k] != a[k]:
match = False
break
if match:
pos.append(j)
if len(pos) == 3: # 找到3个位置就停止
break
if not pos:
print(-1) # 未找到
else:
print(' '.join(map(str, pos))) # 输出位置
elif x == 2:
# 操作2:插入字符串
p = int(op[1]) # 插入位置
a = op[2] # 插入字符串
t = t[:p] + a + t[p:] # 切片插入
print(t) # 输出结果
else:
# 操作3:翻转指定区间
l = int(op[1]) # 左边界
r = int(op[2]) # 右边界
# 切片翻转:取[l:r+1],翻转,放回原串
t = t[:l] + t[l:r+1][::-1] + t[r+1:]
print(t) # 输出结果
solve()
关键点标注
- 操作1 :枚举所有可能的起始位置
j,逐一验证子串a是否匹配,记录最多前3个位置 - 操作2 :Python 字符串切片
t[:p] + a + t[p:]实现插入 - 操作3 :切片+翻转拼接
t[l:r+1][::-1]实现区间翻转
L2-1 姥姥改作业
题意
给定n本作业的混乱指数与初始阈值T,按混乱指数≤T直接批改、>T暂存的规则处理。无待批改作业时T更新为暂存作业混乱指数的平均值并继续处理暂存作业。最终输出作业的批改编号顺序。
思路
用两个栈模拟批改过程:
- 右手栈
a:存储待处理的作业(按输入顺序) - 左手栈
b:存储暂存的作业 - 每轮把当前堆里满足
ci ≤ T的作业按顺序输出,把ci > T的放到左手栈 - 当前堆空后用左手栈混乱指数平均值更新
T,继续直到全部处理完
代码
python
def solve():
n, T = map(int, input().split())
c = [0] + list(map(int, input().split())) # 混乱指数,1-indexed
a = [] # 右手栈(待处理)
b = [] # 左手栈(暂存)
v = [] # 结果
# 初始化右手栈:倒序压入(从最新到最旧)
for i in range(n, 0, -1):
a.append(i)
while True:
# 处理右手栈中 <= T 的作业
while a and c[a[-1]] <= T:
x = a.pop()
v.append(x) # 输出批改
if not a: # 右手栈空,检查是否结束
break
# 右手栈空,说明这批处理完了
if not a:
break
# 左手栈中 > T 的移到右手栈(本轮不处理)
while b and c[b[-1]] > T:
x = b.pop()
a.append(x) # 暂存的放回去等待下一轮
# 更新阈值 T 为暂存作业的平均混乱指数
if not b:
break # 左手栈空,全部处理完毕
s = sum(c[x] for x in in b])
T = s // len(b)
a, b = b, a # # 交换左右手栈
# 输出结果
print(' '.join(map(str, v)))
solve()
关键点标注
- 栈
a(右手):存放当前轮待处理的作业 - 栈
b(左手):存放暂存作业,下一轮变成待处理 - 交换栈 :
a, b = b, a实现下一轮处理暂存作业 - 阈值更新:暂存作业的平均混乱指数(整数除法)
L2-2 超参数搜索
题意
给定n个参数组合的性能得分,先按升序输出所有得分最高的参数组合编号;再处理m次查询,每次查询目标得分x,从性能得分>x`的组合中找到得分最小(得分相同时取编号最小)的组合编号,不存在则输出0。
思路
- 结构体存储每个参数组合的性能得分和对应的序号
- 按得分升序且序号升序排序
- 顺序输出所有得分最高的
max序号(注意:得分相同时取编号最小,排序时自然满足) - 查询用二分查找找第一个得分
>x`的参数组合
代码
python
def solve():
n = int(input())
# 存储每个参数组合:得分和编号
a = []
for i in range(n):
mk = int(input())
a.append((mk, i + 1)) # (得分, 编号)
# 按得分升序,得分相同时编号升序
a.sort(key=lambda x: (x[0], x[1]))
# 收集所有得分最高的max参数组合编号
mx = []
for i in range(n - 1, -1, -1): # 倒序遍历找最高得分
if not mx or a[i][0] == mx[-1][0]:
mx.append(a[i][1])
else:
break
mx.sort() # 编号升序输出
print(' '.join(map(str, mx)))
m = int(input())
for _ in range(m):
x = int(input())
if x >= a[-1][0]:
print(0)
continue
# 二分查找:找第一个得分 > x 的位置
l, r = 0, n - 1
ans = 0
while l <= r:
mid = (l + r) // 2
if a[mid][0] > x:
ans = a[mid][1]
r = mid - 1
else:
l = mid + 1
print(ans)
solve()
关键点标注
- 排序键 :
key=lambda x: (x[0], x[1])实现得分升序、同分编号升序 - 收集最高分:倒序遍历,收集所有最大得分对应的编号
- 二分查找 :找第一个得分严格
>x`的位置,返回其编号
L2-3 森林藏宝图
题意
给定一棵以0为入口(根节点)、共n个节点的树,每条边带安全系数权值;对每个藏宝地(叶子节点),计算从0到该节点路径上所有边权的最小值;找出这些最小值中的最大值,并按升序输出所有取到该最大值的藏宝地编号。
思路
- 从入口
0BFS/DFS遍历整棵树 - 对每个点维护"到该点路径上的最小安全系数":
f[v] = min(f[u], w),即父节点到该点的最小值与边权的较小者 - 在所有叶子中找这个值的最大者
- 按升序输出达到该最大值的藏宝地编号
代码
python
def solve():
n = int(input())
# 邻接表存树,(子节点, 边权)
g = [[] for _ in range(n)]
d = [0] * n # 度数(用于判断叶子)
from collections import deque
q = deque()
for i in range(1, n):
p, s = map(int, input().split())
g[p].append((i, s)) # 子节点i,边权s
d[p] += 1 # 父节点度数+1
INF = float('inf')
f = [INF] * n # f[v] = 到v路径上的最小安全系数
f[0] = INF
q.append(0)
# BFS遍历
while q:
u = q.popleft()
for v, w in g[u]:
# 状态转移:父路径最小值 与 当前边权的较小者
f[v] = min(f[u], w)
q.append(v)
# 找叶子中的最大值
mx = 0
for i in range(1, n):
if d[i] == 0: # 叶子节点度数为0
mx = max(mx, f[i])
print(mx)
# 收集所有达到最大值的叶子编号
v = []
for i in range(1, n):
if d[i] == 0 and f[i] == mx:
v.append(i)
print(' '.join(map(str, v)))
solve()
关键点标注
- BFS遍历 :按层次从根
0开始,保证父节点先于子节点处理 - 状态转移方程 :
f[v] = min(f[u], w)维护路径最小值 - 叶子判断 :
d[i] == 0且i != 0(根节点度可能为0但不是叶子)
L2-4 大语言模型的推理
题意
给定n个想法和m个单向思维跳跃关系(id1引出id2的概率为p%),对每个根思维节点按"优先选概率最高的子想法,概率相同时选编号最小的,不重复访问"的规则逐步推理,直到无新想法可生成。按顺序输出每条推理路径。
思路
- 先对每个想法的出边按概率降序且编号升序排序
- 对每个起点按这个顺序贪心选择第一个未访问后继一路前进
- 标记访问,直到没有可走边为止输出整条路径
代码
python
def solve():
n, m = map(int, input().split())
# 邻接表存图,(目标节点, 概率)
g = [[] for _ in in range(n + 1)]
for _ in range(m):
x, y, p = map(int, input().split())
g[x].append((y, p))
# 对每个节点的出边排序:概率降序,概率相同编号升序
for i in range(1, n + 1):
g[i].sort(key=lambda pair: (-pair[1], pair[0]))
k = int(input())
a = list(map(int, input().split())) # k个起点
vis = [0] * (n + 1) # 访问标记,0未访问,>0已访问
t = 0 # 时间戳/轮次标记
for start in a:
t += 1
u = start
vis[u] = t # 标记当前轮次访问
path = [str(u)] # 记录路径
while True:
# 找第一个未访问的后继
v = 0
for next_node, prob in g[u]:
if vis[next_node] != t: # 未在本轮访问过
v = next_node
break
if v == 0: # 无未访问后继
break
path.append(str(v))
u = v
vis[u] = t # 继续标记访问
print('->'.join(path))
solve()
关键点标注
- 排序键 :
key=lambda pair: (-pair[1], pair[0])概率降序、同概率编号升序 - 访问标记 :
vis[u] = t用轮次编号区分不同轮次的访问,每轮独立 - 贪心选择:每步选概率最大且未本轮访问的后继