第十六届蓝桥杯软件赛省赛PythonB组题解-解题报告

写在前面

赛题相较于上一年py b组难度明显降低,或许成为本次比赛最简单的一套题,当然其中出现了原题,H题为Codeforces原题,分数为1700,裸题(是好事,至少说人话了),题主因时间冲突并未参加正赛,选择了场外vp。个人感觉如果仅有语法基础的话最少可以拿到15分,即通过A题和C题,这样看来最少都得有个省三省二。
本场难度cf预估分数 <=1700。

题解

A 攻击次数 填空题

在这里插入图片描述
103 简单模拟即可,可在草稿纸上手算。

B 最长字符串(填空题)

在这里插入图片描述
答案是afplcu,长度为6

res = set()
path = r"words.txt"
with open(path, "r", encoding="utf-8") as f:
    for line in f:
        cur = line.strip()
        res.add((len(cur), cur))
res = sorted(res)
is_beautiful = set()
ans = -1
l = 0
for length, word in res:
    v = [0] * 26
    if length == 1:
        for i in word:
            v[ord(i) - ord('a')] += 1
        is_beautiful.add(tuple(v))
    else:
        for i in range(length):
            v[ord(word[i]) - ord('a')] += 1
        v1 = [0] * 26
        t1 = word[:-1]
        for i in range(length - 1):
            v1[ord(t1[i]) - ord('a')] += 1
        if  tuple(v1) in is_beautiful:
            is_beautiful.add(tuple(v))
            if length > l:
                l = length
                ans = word
            elif length == l and word < ans:
                ans = word
print(l)
print(ans)

C LQ图形

在这里插入图片描述
思路:签到题,按题意模拟即可

w, h, v = map(int, input().split())
for _ in range(h):
    print('Q' * w)
for _ in range(w):
    print('Q' * (v + w))

D 最多次数

在这里插入图片描述

思路:贪心,注意到先选总是不劣于后选即可

s = input()
n = len(s)
count = 0
i = 0
while i <= n - 3:
    a, b, c = s[i], s[i+1], s[i+2]
    if {a, b, c} == {'l', 'q', 'b'}:
        count += 1
        i += 3
    else:
        i += 1
print(count)

E题 A · B Problem

在这里插入图片描述

思路:用调和级数nlogn预处理出1 - L 每个数的因数个数再O(L)处理出小于等于x的数的乘积对数

最后枚举XA · XB的值即可

L = int(input())

inv = [0] * (L+1)
for i in range(1, L+1):
    for j in range(i, L+1, i):
        inv[j] += 1
dp = [0] * (L+1)
for i in range(1, L+1):
    dp[i] = dp[i-1] + inv[i]
res = 0
for i in range(1, L):
    res += inv[i] * dp[L - i]
print(res)

F 园艺

在这里插入图片描述

思路:动态规划 n^2的解, dp[i][j]表示以第i棵树为起点,间隔为j最多可以保留几颗树

不难观察到有dp[i][j] = dp[i + j][j] + 1 if tree[i+j] > tree[i] else 1

n = int(input())
line = list(map(int, input().split()))
dp = [[0] * n for _ in range(n)]
res = 0
for i in range(n - 1, -1, -1):
    for j in range(1, n):
        if i + j < n:
            if line[i + j] > line[i]:
                dp[i][j] = dp[i + j][j] + 1
            else:
                dp[i][j] = 1
        else:
            dp[i][j] = 1
        res = max(res, dp[i][j])
print(res)

从数据范围来看,显然不是正解,欢迎在评论区分享你的做法。
在这里插入图片描述

G 书架还原

在这里插入图片描述
你没看错,这题很裸,就差把“置换环”告诉你了。这里提供两种做法。

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

def G1(a):
    visited = [False] * n
    cycles = 0

    for i in range(n):
        if not visited[i]:
            j = i
            while not visited[j]:
                visited[j] = True
                j = a[j] - 1  
            cycles += 1
    return n - cycles
def G2(a):
    dic = {}
    for i,x in enumerate(a):
        dic[x] = i
    res = 0
    for val in range(1, n+1):
        val_idx = dic[val]
        cur_idx = val - 1
        if cur_idx == val_idx: continue
        cur = a[cur_idx]
        dic[val] = cur_idx
        dic[cur] = val_idx
        a[val_idx], a[cur_idx] = a[cur_idx], a[val_idx]
        res += 1
    return res
print(G1(a), G2(a))

H 异或和

在这里插入图片描述
cf原题链接:https://codeforces.com/problemset/problem/1879/D
在这里插入图片描述
是不是一模一样呢
思路:拆位算贡献 + 二阶后缀和

n = int(input())

l = list(map(int, input().split()))
res = 0
for i in range(21):
    suf1 = [0] * (n + 1)
    suf2 = [0] * (n + 1)
    for j in range(n-1, -1, -1):
        if (l[j] >> i) & 1:
            suf1[j] = suf1[j+1] + 1
            suf2[j] = suf2[j+1] + suf1[j + 1]
        else:
            suf1[j] = suf1[j+1]
            suf2[j] = suf2[j+1] + suf1[j + 1]
        cnt_1 = suf2[j]
        cnt_0 = (n - j) * (n - j - 1) // 2 - cnt_1
        if (l[j] >> i) & 1:
            res += cnt_0 * (1 << i)
        else:
            res += cnt_1 * (1 << i)
print(res)

写在最后

感谢white_two同学提供的部分代码~
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值