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


前言


题解

这场感觉有点难,D完全没思路, EF很典,能够学到知识.

E我的思路是容斥+贡献,F很典,上周考过一次,引入虚拟节点质数(有点像种类并查集类似的技巧).


欢迎关注

珂朵莉 牛客周赛专栏

珂朵莉 牛客小白月赛专栏


A. 小红的整数自增

题型: 签到

贪心即可,所以值往最大值靠拢即可

python3 复制代码
arr = list(map(int, input().split()))
 
z = max(arr)
 
res = 0
for v in arr:
    res += (z - v)
     
print (res)

B. 小红的伪回文子串(easy)

思路: 暴力

暴力枚举+模拟即可

python3 复制代码
s = input()

def compute(cs):
    res = 0
    i, j = 0, len(cs) - 1
    while i < j:
        if cs[i] != cs[j]:
            res += 1
        i+=1
        j-=1
    return res
       
n = len(s)
res = 0
for i in range(n):
    for j in range(i, n):
        res += compute(s[i:j+1])
        
print (res)

C. 小红的01串取反

思路: 模拟

模拟即可,顺序执行相同操作

  • 最后一个元素不等,即无解
  • 最后一个元素相等,即有解,且按序操作最优
python3 复制代码
n = int(input())
s1 = input()
s2 = input()

res = []
ss1 = list(s1)
ss2 = list(s2)

for i in range(n - 1):
    if ss1[i] != ss2[i]:
        res.append([i+1, i+2])
        ss1[i] = '0' if ss1[i] == '1' else '1'
        if i + 1 < n:
            ss1[i+1] = '0' if ss1[i+1]=='1' else '1'

if ss1[-1] != ss2[-1]:
    print (-1)
else:
    print (len(res))
    for (a, b) in res:
        print (a, b)

D. 小红的乘2除2

思路: 枚举+前后缀拆解

可以枚举除2的点,然后快速寻找那个那个点乘2收益最大

所以它的思路非常的直接

  • 预处理x2的结果
  • 枚举除2的点

由于不确定x2的点的位子在枚举点那一侧,所以引入前后缀拆解

这题绕的地方在于, x2和除2太接近,彼此会互相影响

所以这里需要打个补丁,即在(-1, 0, 1)的位子,特殊枚举x2的结果

这就是大致的思路

时间复杂度为 O ( n ) O(n) O(n)

python3 复制代码
n = int(input())
arr = list(map(int, input().split()))

def evalute(arr):
    res = 0
    n = len(arr)
    for i in range(n - 1):
        res += abs(arr[i] - arr[i + 1])
    return res

pre = [0] * n
suf = [0] * n

def gain(i):
    res = 0
    if i >= 1:
        res += abs(arr[i] * 2 - arr[i - 1]) - abs(arr[i] - arr[i - 1])
    if i < n - 1:
        res += abs(arr[i] * 2 - arr[i + 1]) - abs(arr[i] - arr[i + 1])
    return res

def divgain(i):
    res = 0
    if i >= 1:
        res += abs(arr[i] // 2 - arr[i - 1]) - abs(arr[i] - arr[i - 1])
    if i < n - 1:
        res += abs(arr[i] // 2 - arr[i + 1]) - abs(arr[i] - arr[i + 1])
    return res

from math import inf
pre[0] = inf
for i in range(1, n):
    pre[i] = min(pre[i - 1], gain(i - 1))
        
suf[n - 1] = inf
for i in range(n - 2, -1, -1):
    suf[i] = min(suf[i + 1], gain(i + 1))
    
# 前后缀拆解
from math import inf
res = inf
now = evalute(arr)

def recompute(arr, i):
    acc = 0
    for k in (-1, 0, 1, 2):
        if i + k >= 1 and i + k < n:
            acc += abs(arr[i + k] - arr[i + k - 1])
    return acc

for i in range(n):
    res = min(res, now + divgain(i) + min(pre[i - 1] if i >= 1 else inf, suf[i + 1] if i + 1 < n else inf))        
    acc = recompute(arr, i)
    cb = arr[i]
    arr[i] = cb // 2
    for k in (-1, 0, 1):
        if i + k < 0 or i + k >= n:
            continue
        old = arr[i + k]
        arr[i + k] = old * 2
        res = min(res, now + recompute(arr, i) - acc)
        arr[i + k] = old
    arr[i] = cb
    
print (res)

E. 小红的伪回文子串(hard)

思路: 容斥+贡献

正难则反

正面求解很难,所以试试反向解法,就是统计相同的字符对

总的配对数 - 相同配对数

而这边的相同配对(i, j),其实有一个加权,这个加权

w = m i n ( i + 1 , n − j ) w = min(i+1, n - j) w=min(i+1,n−j)

可以先写一个 O ( n 2 ) O(n^2) O(n2)的解法

一旦写出 O ( n 2 ) O(n^2) O(n2)的解法,基本上半只脚迈入成功的道路上了

因为这里能找到一个技巧点,使得时间复杂度降为 O ( N ) O(N) O(N)

python3 复制代码
s = input()
n = len(s)

# 考虑贡献法
r = 0
for i in range(n):
    d = i + 1
    x = n - 1 - i
    if x >= i:
        r += d * (x - i)
        r += d * (d - 1) // 2
    else:
        d2 = (n - i - 1)
        r += (d2 + 1) * d2 // 2

hash = [[] for _ in range(26)]

for (i, c) in enumerate(s):
    p = ord(c) - ord('a')
    hash[p].append(i)
    
res = 0
for i in range(26):
    ls = hash[i]
    m = len(ls)
    
    pre = [0] * (m + 1)
    for j in range(m):
        pre[j + 1] = pre[j] + (n - ls[j])
    
    # 双指针优化
    tmp = 0
    k = m - 1
    for j in range(m):
        while k >= 0 and n - ls[k] < ls[j] + 1:
            k -= 1
        if k > j:
            tmp += (k - j) * (ls[j] + 1)
            tmp += pre[m] - pre[k + 1]
        else:
            tmp += pre[m] - pre[j + 1]
            
    res += tmp

# 容斥
print (r - res)

F. 小红的迷宫行走

思路: 引入虚节点 + 0-1BFS

  • 虚节点为质数
  • 节点到虚节点代价为0
  • 虚节点到节点代价为1

然后就跑一下0-1BFS,即可

python3 复制代码
h, w = list(map(int, input().split()))

g = []
for _ in range(h):
    row = list(map(int, input().split()))
    g.append(row)
    
from math import inf
dp = [[inf] * w for _ in range(h)]

from collections import deque
from collections import defaultdict


# 建图
cnt = defaultdict(list)

es = [[[] for _ in range(w)] for _ in range(h)]

for i in range(h):
    for j in range(w):
        k = 2
        v = g[i][j]
        while k * k <= v:
            if v % k == 0:
                cnt[k].append((i, j))
                es[i][j].append(k)
                while v % k == 0:
                    v = v // k
            k += 1
        if v > 1:
            cnt[v].append((i, j))
            es[i][j].append(v)
            
deq = deque()
deq.append((0, 0, 0, 0))
dp[0][0] = 0

from collections import Counter
opt = Counter()

from math import gcd

while len(deq) > 0:
    op, y, x, c = deq.popleft()
    if op == 0:
        if y + 1 < h:
            if dp[y + 1][x] > c + 1:
                dp[y + 1][x] = c + 1
                deq.append((0, y+ 1, x, c + 1))
        if x + 1 < w:
            if dp[y][x + 1] > c + 1:
                dp[y][x + 1] = c + 1
                deq.append((0, y, x + 1, c+ 1))
                
        for v in es[y][x]:
            if v not in opt:
                opt[v] = c
                deq.appendleft((1, v, 0, c))
    else:
        for (ty, tx) in cnt[y]:
            if dp[ty][tx] > c + 1:
                dp[ty][tx] = c + 1
                deq.append((0, ty, tx, c + 1))

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

写在最后

相关推荐
CryptoRzz几秒前
日本股票 API 对接实战指南(实时行情与 IPO 专题)
java·开发语言·python·区块链·maven
ss273几秒前
考研加油上岸祝福弹窗程序
python
程序员水自流2 分钟前
MySQL数据库自带系统数据库功能介绍
java·数据库·mysql·oracle
旧梦吟6 分钟前
脚本网页 三人四字棋
前端·数据库·算法·css3·html5
谷哥的小弟7 分钟前
Spring Framework源码解析——RequestContext
java·后端·spring·框架·源码
乾元8 分钟前
基于时序数据的异常预测——短期容量与拥塞的提前感知
运维·开发语言·网络·人工智能·python·自动化·运维开发
江上清风山间明月9 分钟前
使用python将markdown文件生成pdf文件
开发语言·python·pdf
凯_kyle9 分钟前
Python 算法竞赛 —— 基础篇(更新ing)
笔记·python·算法
天远Date Lab13 分钟前
Java微服务实战:聚合型“全能小微企业报告”接口的调用与数据清洗
java·大数据·python·微服务
ss27315 分钟前
阻塞队列:ArrayBlockingQueue如何用Lock与Condition实现高效并发控制
开发语言·python