牛客周赛 Round 55 解题报告 | 珂学家
小红的字符串
https://ac.nowcoder.com/acm/contest/87656/A
前言
题解
补题这场比赛,好像还是难。
A. 小红的字符串
签到题
枚举最终的字符,求最小的修改
这个方法更有通用性
s = input()
from math import inf
import string
ans = inf
for c in string.ascii_letters:
ans = min(ans, sum([1 for z in s if z != c]))
print (ans)
B. 小红的序列乘积
思路: 模拟
也是为后续的E题做铺垫
因为关注的个位数,所以乘积的时候,可以, 从而避免大数乘法
n = int(input())
arr = list(map(int, input().split()))
ans = 0
acc = 1
for v in arr:
acc = acc * v % 10
if acc == 6:
ans += 1
print (ans)
C. 小红的数组重排
思路: 贪心构造
移项转化,可以观察到
偶数项
奇数项
两个序列大小没有制约关系
由于是严格小于,所以序列中必然没有3个以上的相同项
注:特别注意0最多一个,而且只能在偶数序列中
- 先分配出现次数为2的数,偶数/奇数序列各一个
- 0这个数一定要放在偶数序列中
- 剩下单个数,那个序列数不足,放哪里
# a1 < a3 < a5
# a2 < a4 < a6
n = int(input())
arr = list(map(int, input().split()))
from collections import Counter
def solve():
m1 = (n + 1) // 2
m2 = n // 2
ext = []
ls1, ls2 = [], []
cnt = Counter(arr)
if cnt[0] >= 2:
return None
for (k, v) in cnt.items():
if v > 2:
return None
if v == 2:
ls1.append(k)
ls2.append(k)
else:
if k == 0:
ls1.append(0)
else:
ext.append(k)
while len(ls1) < m1:
ls1.append(ext.pop())
while len(ls2) < m2:
ls2.append(ext.pop())
# 排序组合
ls1.sort()
ls2.sort()
res = []
for (k1, k2) in zip(ls1, ls2):
res.append(k1)
res.append(k2)
return res
ls = solve()
if ls is None:
print ("NO")
else:
print ("YES")
print (*ls, sep=' ')
D. 虫洞操纵者
思路: BFS
有些绕,遇到1或者边界会存在跳跃情况
n = int(input())
g = []
for _ in range(n):
row = list(map(int, input().split()))
g.append(row)
from math import inf
dp = [[inf] * n for _ in range(n)]
from collections import deque
dp[0][0] = 0
deq = deque()
deq.append((0, 0))
while len(deq) > 0:
y, x = deq.popleft()
for (dy, dx) in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
ty, tx = y + dy, x + dx
if 0 <= ty < n and 0 <= tx < n:
if g[ty][tx] == 0:
if dp[ty][tx] > dp[y][x] + 1:
dp[ty][tx] = dp[y][x] + 1
deq.append((ty, tx))
continue
if dy == -1:
ty += 2
while ty < n and g[ty][tx] == 0:
ty += 1
if g[ty - 1][tx] == 0 and dp[ty - 1][tx] > dp[y][x] + 1:
dp[ty - 1][tx] = dp[y][x] + 1
deq.append((ty - 1, tx))
elif dy == 1:
ty -= 2
while ty >= 0 and g[ty][tx] == 0:
ty -= 1
if g[ty + 1][tx] == 0 and dp[ty + 1][tx] > dp[y][x] + 1:
dp[ty + 1][tx] = dp[y][x] + 1
deq.append((ty + 1, tx))
elif dx == -1:
tx += 2
while tx < n and g[ty][tx] == 0:
tx += 1
if g[ty][tx - 1] == 0 and dp[ty][tx - 1] > dp[y][x] + 1:
dp[ty][tx - 1] = dp[y][x] + 1
deq.append((ty, tx - 1))
elif dx == 1:
tx -= 2
while tx >= 0 and g[ty][tx] == 0:
tx -= 1
if g[ty][tx + 1] == 0 and dp[ty][tx + 1] > dp[y][x] + 1:
dp[ty][tx + 1] = dp[y][x] + 1
deq.append((ty, tx + 1))
#print (dp)
print (dp[-1][-1] if dp[-1][-1] != inf else -1)
E. 小红的序列乘积2.0
思路: 贡献法 + DP
非常好的一道题
引入, 表示前i项中,个位数为s的序列总数
那为何引入贡献法呢?
其实只要出现6,那它就贡献 次数
那这个dp,只需要维护序列总数即可
第一维,可以借助滚动数组优化
这样时间复杂度为, 空间复杂度为
def pow(b, v, m):
r = 1
while v > 0:
if v % 2 == 1:
r = r * b % m
b = b * b % m
v //= 2
return r
n = int(input())
arr = list(map(int, input().split()))
dp = [0] * 10
mod = 10 ** 9 + 7
res = 0
for (i, v) in enumerate(arr):
dp2 = dp[:]
if v % 10 == 6:
res += pow(2, (n - 1 - i), mod)
res %= mod
dp2[v % 10] += 1
lv = v % 10;
for j in range(1, 10):
if j * lv % 10 == 6:
res += dp[j] * pow(2, (n - 1 - i), mod) % mod
res %= mod
dp2[j * lv % 10] += dp[j]
dp2[j * lv % 10] %= mod
dp = dp2
print (res)
F. 灯下定影
下次补上