前言

alt


题解

这真的是牛客周赛? 哭了


欢迎关注

珂朵莉 牛客周赛专栏

珂朵莉 牛客小白月赛专栏


A. 小红的葫芦

签到题

但是写起来有点变扭,方法应该蛮多的

统计分组

  • 有2组
  • 一组长度为2,一组长度为3
def check(arr):
    arr.sort()
    if arr[0] == arr[4]:
        return False
    if arr[0] == arr[1] and arr[2] == arr[4]:
        return True
    if arr[0] == arr[2] and arr[3] == arr[4]:
        return True
    return False

arr = list(map(int, input().split()))
print ("YES" if check(arr) else "NO")

B. 茉茉的密码

思路: 贪心构造

如果s满足要求,s的子串sa,必然满足要求

这样,可以贪心枚举26个字符

n = int(input())

arr = []
for _ in range(n):
    arr.append(input())
    
def check(c, arr):
    for s in arr:
        if c not in s:
            return False
    return True

for i in range(26):
    c = chr(ord('a') + i)
    if check(c, arr):
        print (c)
        break

C. 苗苗的气球

思路: 众数贪心

  • 特判n=1,n=2的情况

  • 枚举每种气球

这个时候,其实只需要讨论当前的气球A,其他的剩余B,其他中的众数C

那ABC满足什么条件,可以保证A有剩余

还要考虑奇偶,因为对消有剩余

def check(a, b, c):
    if (b + c) % 2 == 0:
        if c <= b:
            return True
        elif a > (c - b):
            return True
    else:
        if c <= b:
            return 1 if a >= 2 else 0
        elif a > (c - b):
            return True            
    return False

当然这题,还要想想如何维护众数

引入前后缀拆解, 快速求解除自身以为的众数

n = int(input())

arr = list(map(int, input().split()))

s = sum(arr)


def check(a, b, c):
    if (b + c) % 2 == 0:
        if c <= b:
            return True
        elif a > (c - b):
            return True
    else:
        if c <= b:
            return 1 if a >= 2 else 0
        elif a > (c - b):
            return True            
    return False

def solve():
    if n == 1:
        return 1
    elif n == 2:
        return 1 if arr[0] != arr[1] else 0
    pre = [0] * n
    suf = [0] * n

    # 前后缀拆解
    for i in range(1, n):
        pre[i] = max(pre[i - 1], arr[i])
    for i in range(n - 2, -1, -1):
        suf[i] = max(suf[i + 1], arr[i])

    res = 0
    for i in range(n):
        if i == 0:
            mx = suf[1]
            if check(arr[i], s - arr[i] - mx, mx):
                res += 1
        elif i == n - 1:
            mx = pre[n - 2]
            if check(arr[i], s - arr[i] - mx, mx):
                res += 1
        else:
            mx = max(pre[i - 1], suf[i + 1])
            if check(arr[i], s - arr[i] - mx, mx):
                res += 1
    return res
            
print (solve())

D. 萌萌的好数

思路: 二分+容斥+数位DP

感觉写复杂了,但是过了


# 容斥

t = int(input())

# 数位DP吗?
from functools import cache

@cache
def dfs(s, idx, acc, isLimit, isNum):
    if idx == len(s):
        return 1 if isNum and acc % 3 != 0 else 0
    r = 0
    if not isNum:
        r += dfs(s, idx + 1, 0, False, isNum)
    
    p = ord(s[idx]) - ord('0')
    if idx < len(s) - 1:
        start = 0 if isNum else 1
        end = p if isLimit else 9
        for i in range(start, end + 1):
            r += dfs(s, idx + 1, (acc+i) % 3, isLimit and i == end, True)
    else:
        if not isLimit:
            r += dfs(s, idx + 1, (acc + 3) % 3, False, True)
        else:
            if p >= 3:
                r += dfs(s, idx + 1, acc, p == 3, True)
        
    return r
        
    

def compute(x):
    z = x - x // 3
    # 最后一位为3
    s = str(x)
    m = len(s)
    
    z = z - dfs(s, 0, 0, True, False)
    dfs.cache_clear()
    return z
    
    

for _ in range(t):
    n = int(input())
    l, r = 1, n * 3
    while l <= r:
        m = (l + r) // 2
        if compute(m) < n:
            l = m + 1
        else:
            r = m - 1
    print (l)
        

E. 茜茜的计算器

思路: 容斥

但是这个式子太简单了

横对称的有1,3,8,0

纵对称的有25配对,52配置,00配对,88配对

n = int(input())

mod = 10 ** 9 + 7

r1 = pow(4, n, mod)
r2 = pow(4, n // 2, mod)
if n % 2 == 1:
    r2 = r2 * 2 % mod
    
r3 = pow(2, n // 2, mod)
if n % 2 == 1:
    r3 = r3 * 2 % mod

r = r1 + r2 - r3
print (r%mod)

F. 花花的地图

方法一: 普通dijkstra寻路解法

思路: dijkstra寻路

很典的题,之前看过的同类版本是

  • 破墙(一块)
  • 破墙(2*2)

这边是同列,因为h,w为100

这边遇到墙的时候,需要枚举一列来拓展状态点

核心思想是

所以大概的时间复杂度为

h, w = list(map(int, input().split()))

grid = []
for _ in range(h):
    grid.append(input())
    
cost = list(map(int, input().split()))
    
from math import inf
import heapq

dp = [[inf] * w for _ in range(h)]

hp = []
if grid[0][0] == '.':
    heapq.heappush(hp, (0, 0, 0))
    dp[0][0] = 0
else:
    for i in range(h):
        heapq.heappush(hp, (cost[0], i, 0))
        dp[i][0] = cost[0]
        

while len(hp) > 0:
    c, y, x = heapq.heappop(hp)
    if c > dp[y][x]:
        continue
    
    for dy, dx in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
        ty, tx = y + dy, x + dx
        if 0 <= ty < h and 0 <= tx < w:
            if grid[ty][tx] == '.':
                if dp[ty][tx] > c:
                    dp[ty][tx] = c
                    heapq.heappush(hp, (dp[ty][tx], ty, tx))
            else:
                for j in range(h):
                    if dp[j][tx] > c + cost[tx]:
                        dp[j][tx] = c + cost[tx]
                        heapq.heappush(hp, (dp[j][tx], j, tx))

print (dp[h - 1][w - 1])

方法二:引入虚节点建图

思路: 因为有炸列的操作

  • 为每列引入一个虚拟节点

  • 引入有向边

左右两侧/中间节点,到虚拟节点的代价为cost[i]

虚拟节点到中间列节点的代价为0

alt

  • 建图跑Dijkstra

这样时间复杂度为

如果这题数据范围为n为1e3级别,就很有意思

h, w = list(map(int, input().split()))

grid = []
for _ in range(h):
    grid.append(input())
    
cost = list(map(int, input().split()))
    
from math import inf
import heapq

dp = [[inf] * w for _ in range(h + 1)]

hp = []
if grid[0][0] == '.':
    heapq.heappush(hp, (0, 0, 0))
    dp[0][0] = 0
else:
    heapq.heappush(hp, (cost[0], h, 0))
    dp[h][0] = cost[0]        

while len(hp) > 0:
    c, y, x = heapq.heappop(hp)
    if c > dp[y][x]:
        continue
    
    # 如果是虚节点
    if y == h:
        for i in range(h):
            if dp[i][x] > c:
                dp[i][x] = c
                heapq.heappush(hp, (dp[i][x], i, x))
    else:    
        for dy, dx in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
            ty, tx = y + dy, x + dx
            if 0 <= ty < h and 0 <= tx < w:
                if grid[ty][tx] == '.':
                    if dp[ty][tx] > c:
                        dp[ty][tx] = c
                        heapq.heappush(hp, (dp[ty][tx], ty, tx))
        
        for dx in (-1, 0, 1):
            if 0 <= x + dx < w:
                if dp[h][x + dx] > c + cost[x + dx]:
                    dp[h][x + dx] = c + cost[x + dx]
                    heapq.heappush(hp, (dp[h][x + dx], h, x + dx))

#print (dp)
print (dp[h - 1][w - 1])

写在最后

alt