写在前面
赛题相较于上一年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同学提供的部分代码~