[牛客周赛复盘] 牛客周赛 Round 1 20230702

[牛客周赛复盘] 牛客周赛 Round 1 20230702

    • 总结
    • 游游画U
      • 1. 题目描述
      • 2. 思路分析
      • 3. 代码实现
    • 游游的数组染色
      • 1. 题目描述
      • 2. 思路分析
      • 3. 代码实现
    • 游游的交换字符
      • 1. 题目描述
      • 2. 思路分析
      • 3. 代码实现
    • 游游的9的倍数
      • 1. 题目描述
      • 2. 思路分析
      • 3. 代码实现
    • 六、参考链接

总结

  • 牛客第一次,据说排名系统还在测试环境哈哈。
  • A 大模拟。
  • B 分类计数。
  • C 贪心双指针模拟。
  • D 同余dp.[牛客周赛复盘] 牛客周赛 Round 1 20230702_第1张图片

游游画U

链接: 游游画U

1. 题目描述

[牛客周赛复盘] 牛客周赛 Round 1 20230702_第2张图片

2. 思路分析

不擅长这种画图大模拟。
  • 发现前边的行全是一样的先初始化4n行。
  • 然后从最后一行开始倒着覆盖,枚举中间的空格。

3. 代码实现

# Problem: 游游画U
# Contest: NowCoder
# URL: https://ac.nowcoder.com/acm/contest/60245/A
# Memory Limit: 524288 MB
# Time Limit: 2000 ms

import sys
import random
from types import GeneratorType
import bisect
import io, os
from bisect import *
from collections import *
from contextlib import redirect_stdout
from itertools import *
from array import *
from functools import lru_cache, reduce
from heapq import *
from math import sqrt, gcd, inf

if sys.version >= '3.8':  # ACW没有comb
    from math import comb

RI = lambda: map(int, sys.stdin.buffer.readline().split())
RS = lambda: map(bytes.decode, sys.stdin.buffer.readline().strip().split())
RILST = lambda: list(RI())
DEBUG = lambda *x: sys.stderr.write(f'{str(x)}\n')
# print = lambda d: sys.stdout.write(str(d) + "\n")  # 打开可以快写,但是无法使用print(*ans,sep=' ')这种语法,需要print(' '.join(map(str, p))),确实会快。

DIRS = [(0, 1), (1, 0), (0, -1), (-1, 0)]  # 右下左上
DIRS8 = [(0, 1), (1, 1), (1, 0), (1, -1), (0, -1), (-1, -1), (-1, 0),
         (-1, 1)]  # →↘↓↙←↖↑↗
RANDOM = random.randrange(2 ** 62)
MOD = 10 ** 9 + 7
# MOD = 998244353
PROBLEM = """
"""


def lower_bound(lo: int, hi: int, key):
    """由于3.10才能用key参数,因此自己实现一个。
    :param lo: 二分的左边界(闭区间)
    :param hi: 二分的右边界(闭区间)
    :param key: key(mid)判断当前枚举的mid是否应该划分到右半部分。
    :return: 右半部分第一个位置。若不存在True则返回hi+1。
    虽然实现是开区间写法,但为了思考简单,接口以[左闭,右闭]方式放出。
    """
    lo -= 1  # 开区间(lo,hi)
    hi += 1
    while lo + 1 < hi:  # 区间不为空
        mid = (lo + hi) >> 1  # py不担心溢出,实测py自己不会优化除2,手动写右移
        if key(mid):  # is_right则右边界向里移动,目标区间剩余(lo,mid)
            hi = mid
        else:  # is_left则左边界向里移动,剩余(mid,hi)
            lo = mid
    return hi


def bootstrap(f, stack=[]):
    def wrappedfunc(*args, **kwargs):
        if stack:
            return f(*args, **kwargs)
        else:
            to = f(*args, **kwargs)
            while True:
                if type(to) is GeneratorType:
                    stack.append(to)
                    to = next(to)
                else:
                    stack.pop()
                    if not stack:
                        break
                    to = stack[-1].send(to)
            return to

    return wrappedfunc


#       ms
def solve():
    n, = RI()
    ans = ['' for _ in range(4 * n)]
    for i in range(4 * n):
        ans[i] = ('*' * n + '.' * (2 * n) + '*' * n)
    x = 0
    for i in range(4 * n - 1, -1, -1):
        s = ['.'] * (4 * n)
        r = 4 * n // 2 + x
        l = 4 * n // 2 - 1 - x
        # print(l,r)
        for j in range(r, r + n):
            s[j] = '*'
            # print(j)
        for j in range(l, l - n, -1):
            s[j] = '*'
        x += 1
        ans[i] = ''.join(s)
        if x == n: break
    for s in ans:
        print(s)


if __name__ == '__main__':
    t = 0
    if t:
        t, = RI()
        for _ in range(t):
            solve()
    else:
        solve()

游游的数组染色

链接: 游游的数组染色

1. 题目描述

[牛客周赛复盘] 牛客周赛 Round 1 20230702_第3张图片

2. 思路分析

  • 数字相同的分一组,计数r和b。
  • 对每种数字里,累计r*b的数量即可。

3. 代码实现

#       ms
def solve():
    n, = RI()
    a = RILST()
    cs, = RS()
    cnt = defaultdict(Counter)
    ans = 0
    for v, c in zip(a, cs):
        cnt[v][c] += 1
    for v in cnt.values():
        x, y = v['R'], v['B']
        ans += x * y
    print(ans)

游游的交换字符

链接: 游游的交换字符

1. 题目描述

[牛客周赛复盘] 牛客周赛 Round 1 20230702_第4张图片

2. 思路分析

需要先想到一个性质,一开始没想到卡半天去D了先。
  • 题目保证一定有解。那么1和0的出现次数只差一定<=1。
  • 比如01出现次数分别是x,x+1,那么最后构造的解一定是1010…101;相反就是0101…010
  • 若01出现次数相同,那么构造的串可能是010101或者101010。
  • 知道最终结果的话,那么题目转化成交换相邻串,如何从s变成t,这个就很典了。
  • 双指针把最近的1移动到最近位置即可。

3. 代码实现

def f(s, t):
    # print(s,t)
    n = len(s)
    j = 0
    ans = 0
    for i, v in enumerate(s):
        while j < n and t[j] != '1':
            j += 1
        if v == '1':
            ans += abs(i - j)
            j += 1
    return ans


#       ms
def solve():
    s, = RS()
    one = s.count('1')
    zero = s.count('0')
    # print(one,zero)
    if one == zero:
        ans = min(f('01' * one, s), f('10' * one, s))
    elif one > zero:
        ans = f(s, '10' * zero + '1')
    else:
        ans = f(s, '01' * one + '0')
    print(ans)

游游的9的倍数

链接: 游游的9的倍数

1. 题目描述

[牛客周赛复盘] 牛客周赛 Round 1 20230702_第5张图片

2. 思路分析

  • 典。同余dp。
  • 令f[i][j]为前i个数字组成的,子序列模9为j时的子序列个数。
  • 那么添加一个数字s[i]时,尝试把前一步(*10+s[i])%9即可。
  • 注意额外单独添加s[i]自己。

3. 代码实现

def solve():
    s, = RS()
    s = list(map(int, s))
    cnt = [0] * 9
    ans = 0
    for v in s:
        f = [0] * 9
        for j, c in enumerate(cnt):
            p = (j * 10 + v) % 9
            if p == 0:
                ans = (ans + c) % MOD
            f[p] += c
        if v % 9 == 0:
            ans = (ans + 1) % MOD

        f[v % 9] += 1
        for i, v in enumerate(f):
            cnt[i] = (cnt[i] + v) % MOD

    print(ans)

六、参考链接

你可能感兴趣的:(牛客比赛复盘,python)