[牛客周赛复盘] 牛客周赛 Round 1 20230702
- 总结
- 游游画U
- 1. 题目描述
- 2. 思路分析
- 3. 代码实现
 
- 游游的数组染色
- 1. 题目描述
- 2. 思路分析
- 3. 代码实现
 
- 游游的交换字符
- 1. 题目描述
- 2. 思路分析
- 3. 代码实现
 
- 游游的9的倍数
- 1. 题目描述
- 2. 思路分析
- 3. 代码实现
 
- 六、参考链接
 
总结
- 牛客第一次,据说排名系统还在测试环境哈哈。
- A 大模拟。
- B 分类计数。
- C 贪心双指针模拟。
- D 同余dp. 
游游画U
链接: 游游画U
1. 题目描述

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. 题目描述

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. 题目描述

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. 题目描述

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)
六、参考链接
- 无



















