牛客周赛 Round 55 解题报告 | 珂学家


前言

alt


题解

补题这场比赛,好像还是难。


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题做铺垫

因为关注的个位数,所以乘积的时候,可以 m o d   10 mod \ 10 mod 10, 从而避免大数乘法

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. 小红的数组重排

思路: 贪心构造

移项转化,可以观察到

偶数项 a 0 < a 2 < a 4 < . . . < a x , x 是偶数 { a_0 < a_2 < a_4 < ... < a_x, x是偶数} a0<a2<a4<...<ax,x是偶数

奇数项 a 1 < a 3 < a 5 < . . . < a y , y 是奇数 { a_1 < a_3 < a_5 < ... < a_y, y是奇数} a1<a3<a5<...<ay,y是奇数

两个序列大小没有制约关系

由于是严格小于,所以序列中必然没有3个以上的相同项

注:特别注意0最多一个,而且只能在偶数序列中

  1. 先分配出现次数为2的数,偶数/奇数序列各一个
  2. 0这个数一定要放在偶数序列中
  3. 剩下单个数,那个序列数不足,放哪里

# 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

非常好的一道题

引入 d p [ i ] [ s ] , s ∈ [ 0 , 9 ] {dp[i][s], s \in [0, 9]} dp[i][s],s[0,9], 表示前i项中,个位数为s的序列总数

那为何引入贡献法呢?

其实只要出现6,那它就贡献 d p [ i ] [ 6 ] ∗ 2 n − 1 − i dp[i][6] * 2^{n - 1 - i} dp[i][6]2n1i 次数

那这个dp,只需要维护序列总数即可

第一维,可以借助滚动数组优化

这样时间复杂度为 O ( 10 ∗ n ) O(10 * n) O(10n), 空间复杂度为 O ( 10 ) O(10) O(10)

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. 灯下定影

下次补上



写在最后

alt

  • 17
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值