牛客周赛 Round 47 解题报告 | 珂学家
小红的葫芦
https://ac.nowcoder.com/acm/contest/84851/A
前言
题解
这真的是牛客周赛? 哭了
欢迎关注
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
- 建图跑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])