团体程序设计天梯赛 2025 – Python 个人赛时暴力题解



前言

第一次参加天梯赛,虽然不是队里分数最低的,也不是第二低的,在队里的位置来说还是拖后腿了。

忘记复制题面了,只有赛事题解。题面有机会后补。

原来想纯用那个网页调试的,但是网页一直无法使用,所以开了 PyCharm。

教训:

  1. 菜就多练
  2. 用 Python = TLE,本篇出现题解未拿满分都是爆点 TLE
  3. 提前开好 IDE

每个代码块开头的注释意为:{实际得分}/{此题总分}

L1-1

签到

# 5/5
print("Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.")

L1-2

签到

# 5/5
a, b, c = map(int, input().split())
print(a + b + c)

L1-3

阅读理解

# 10/10
T, S, t = map(int, input().split())

if T > 35 and t >= 33:
    if S == 0:
        print("Shi Nei")
        print(T)
    else:
        print("Bu Tie")
        print(T)
else:
    if S == 1:
        print("Bu Re")
        print(t)
    else:
        print("Shu Shi")
        print(t)

L1-4

转换为二进制,保留最高位的 1,其余都清 0,再转回十进制,输出答案即可。

# 10/10
print(int("1" + (len(bin(int(input()))[2:]) - 1) * "0", 2))

L1-5

# 15/15
s = input()
l = list(map(int, input().split()))
charmap = {}
sum = 0
for c in s:
    sum += l[ord(c) - ord("a")]
    if c in charmap:
        charmap[c] += 1
    else:
        charmap[c] = 1
# 赛时脑梗,可以直接
# for i in range(ord('a'), ord('z')):
for i in ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y']:
    if i in charmap:
        print(charmap[i], end=" ")
    else:
        print(0, end=" ")
# 不能有行末空格,故单独检查
if "z" in charmap:
    print(charmap["z"])
else:
    print(0)
print(sum)

L1-6

# 10/15
N, M = map(int, input().split())
# 部分 action 需要 str,部分 action 需要 list
# 预先处理为 list,需要时转换为 str 一样 TLE 扣五分
alist_str = input()
for _ in range(M):
    action = int(input())
    if action == 1:
        llist = input()
        llist_str = llist[llist.find(" ") + 1 :]
        llist2 = input()
        llist2_str = llist2[llist2.find(" ") + 1 :]
        if llist_str in alist_str:
            alist_str = alist_str.replace(llist_str, llist2_str, 1)
    elif action == 2:
        new_alist = []
        b = None
        for i in map(int, alist_str.split()):
            if b is None:
                b = i
                continue
            if (b + i) % 2 == 0:
                new_alist.append(b)
                new_alist.append(int((b + i) / 2))
                b = i
            else:
                new_alist.append(b)
                b = i
        new_alist.append(b)
        alist_str = " ".join(map(str, new_alist))
    else:
        index_s, index_e = map(int, input().split())
        alist = list(map(int, alist_str.split()))
        alist = (
            alist[: index_s - 1] + alist[index_s - 1 : index_e][::-1] + alist[index_e:]
        )
        alist_str = " ".join(map(str, alist))
print(alist_str)

L1-7

# 19/20
n = int(input())
s = 0
c = 31
nn = 1
flag = False
passflag = False
while True:
    if not passflag:
        if 1 + 2**c > n:
            s = 0
            c -= 1
            nn = 1
            if c == 0:
                break
            passflag = False
            continue
        else:
            passflag = True
    s += nn**c
    if s < n:
        nn += 1
    elif s == n:
        flag = True
        break
    else:
        s = 0
        c -= 1
        nn = 1
        passflag = False
        continue
if flag:
    for i in range(1, nn):
        print(f"{i}^{c}+", end="")
    print(f"{nn}^{c}")
else:
    print(f"Impossible for {n}.")

L1-8

思路是计算出每行里最大的数字(计算每列最大的数字也一样),将价值和坐标存入数组 line_max。按价值从大到小遍历数组 line_max,记录点的行号和列号,要是出现相同的行号和列号就跳过这个点。

# 15/20
n, m, k = map(int, input().split())
mm = [[[0] for _ in range(m)] for _ in range(n)]
line_max = []

# 读取 + 预处理得出每行最大价值目标
for _ in range(n):
    mm[_] = list(map(int, input().split()))
    max_n = "-INF"
    l = -1
    for index, n in enumerate(mm[_]):
        if max_n == "-INF" or n > max_n:
            max_n = n
            l = index
    line_max.append((max_n, _, l))

c = 0  # 当前攻击数
dead_h = set()  # 记录已摧毁的行号
dead_l = set()  # 记录已摧毁的列号

for point in sorted(line_max, key=lambda a: a[0], reverse=True):
    if c == k:
        # 达到攻击数上限
        break

    # 检查行号和列号是否出现过
    if point[1] in dead_h:
        continue
    if point[2] in dead_l:
        continue

    c += 1
    # 记录行号和列号
    dead_h.add(point[1])
    dead_l.add(point[2])

# 输出时跳过已摧毁的行号和列号
new_mm = []
for index, h in enumerate(mm):
    if index in dead_h:
        continue
    temp_h = []
    for index_2, l in enumerate(h):
        if index_2 in dead_l:
            continue
        temp_h.append(l)
    new_mm.append(temp_h)
for _ in new_mm:
    print(" ".join(map(str, _)))

L2-1

中缀转后缀,然后按计算过程输出,但不输出计算过程中的数。
菜鸡忘了咋写了,现推,最后爆几个 TLE。

# 15/25
s = input()
pc = []
temp = []
sign = ["*", " "+", "-"]
end = []
ihave_left = 0
for _ in s:
    if _ not in sign:
        if _ not in ["(", ")"]:
            pc.append(_)
            if ihave_left == 0:
                pc.append(temp.pop())
            continue
        if _ == ")":
            ihave_left -= 1
            pc.append(temp.pop())
            pc.append(")")
            continue
        if _ == "(":
            pc.append("(")
            ihave_left += 1
            continue
    else:
        if pc[-1] in sign and (pc[-1] in ("+", "-") and _ in ("*", "
            temp.append(pc.pop())
        temp.append(_)
while temp:
    pc.append(temp.pop())
ca_list = []
for _ in pc:
    if _ in ("(", ")"):
        continue
    if _ in sign:
        b, b_s = ca_list.pop()
        a, a_s = ca_list.pop()
        print(f"{a if a_s==0 else ''}{_}{b if b_s==0 else ''}")
        ca_list.append((str(eval(f"{a}{_}{b}")), 1))
    else:
        ca_list.append((_, 0))

L2-2

暴力检查

# 16/25
from functools import cmp_to_key

n = int(input())
g0 = set()
g1 = set()
g2 = set()
for _ in range(n):
    x, y = list(map(int, input().split()))
    if y == 0:
        g0.add(x)
    elif y == 1:
        g1.add(x)
    else:
        g2.add(x)
ans = []
for x1 in g0:
    for x2 in g1:
        x3 = x2 + (x2 - x1)
        if x3 in g2:
            ans.append([x1, x2, x3])


def cmp(a, b):
    if a[1] < b[1]:
        return -1
    elif a[1] > b[1]:
        return 1
    else:
        if a[0] < b[0]:
            return -1
        elif a[0] > b[0]:
            return 1
        else:
            return 0


ans.sort(key=cmp_to_key(cmp))
if not ans:
    print(-1)
else:
    for a in ans:
        x1, x2, x3 = a
        print(f"[{x1}, 0] [{x2}, 1] [{x3}, 2]")

其他

L2-3 想读取全部时间,然后分块判断,但没写。
L2-4 写一半

n,a,b=list(map(int,input().split()))

def k(_):
    for c in str(_)[::-2]:
        if c not in ('0', '2', '4', '6', '8'):
            return True
    return False

def k2(_):
    for c in str(_)[-2::-2]:
        if c not in ('0', '2', '4', '6', '8'):
            return True
    return False

for _ in range(a,b+1):
    if n>=10:
        if str(_)[9] != '0':
            continue
    if n>=5:
        if str(_)[4] not in ('0','5'):
            continue
    if len(_)%2==0:
        if k(_):
            continue
    else:
        if k2(_):
            continue
# 未完成

时间把握不当,最后在

  1. 把前面的优化
  2. 重写为 C++
  3. 嫖分
  4. 再写一题

中选择的了选项 4。
从结果来看是最差的选项。

后记

最后总分 120,个人有效分 120。
队里大哥带飞,队伍得分 1457。