[acwing周赛复盘] 第 60 场周赛20220716

一、本周周赛总结

  • 第一次打acwing,一共三题,难度跳跃挺大。
  • acwing python竟然不支持from math import comb,震惊!还得自己实现。
  • 在这里插入图片描述

在这里插入图片描述

二、 4722. 数列元素

链接: 4722. 数列元素

1. 题目描述

在这里插入图片描述

2. 思路分析

  • 直接从1到n枚举,计算等比数列和即可。

3. 代码实现

import sys
from collections import *
from contextlib import redirect_stdout
from itertools import *
from math import sqrt
from array import *
from functools import lru_cache
import heapq
import bisect
import random
import io, os
from bisect import *

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')

MOD = 10 ** 9 + 7




def main():
    n, = RI()
    for i in range(1,n+1):
        if i*(i+1)//2 == n:
            return print('YES')
    print('NO')


if __name__ == '__main__':
    # testcase 2个字段分别是input和output
    test_cases = (
        (
            """
1
""",
            """
YES
"""
        ),
        (
            """
2
""",
            """
NO
"""
        ),
        (
            """
3
""",
            """
YES
"""
        ),
    )
    if os.path.exists('test.test'):
        total_result = 'ok!'
        for i, (in_data, result) in enumerate(test_cases):
            result = result.strip()
            with io.StringIO(in_data.strip()) as buf_in:
                RI = lambda: map(int, buf_in.readline().split())
                RS = lambda: buf_in.readline().strip().split()
                with io.StringIO() as buf_out, redirect_stdout(buf_out):
                    main()
                    output = buf_out.getvalue().strip()
                if output == result:
                    print(f'case{i}, result={result}, output={output}, ---ok!')
                else:
                    print(f'case{i}, result={result}, output={output}, ---WA!---WA!---WA!')
                    total_result = '---WA!---WA!---WA!'
        print('\n', total_result)
    else:
        main()

三、4723. 队列

链接: 4723. 队列

1. 题目描述

在这里插入图片描述

2. 思路分析

  • 模拟一下可知,出队数据会被分成k个部分,第一部分有5个元素,第二部分是第一部分double:10个,第三部分20。。。
  • 我们让n依次减去这些部分,直到n无法构成下一个完整的部分。
  • 计算剩余的n在这个部分的哪个区域,区域的大小是x//5
  • 复杂度显然是开方的,因为是减去等差数列求和,这个和将以x方的速度增长到n。

3. 代码实现

import sys
from collections import *
from contextlib import redirect_stdout
from itertools import *
from math import sqrt
from array import *
from functools import lru_cache
import heapq
import bisect
import random
import io, os
from bisect import *

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')
MOD = 10 ** 9 + 7


#    	 ms
def solve(n):
    a = 'abcde'
    if n <= 5:
        return print(a[n-1])
    x = 5
    while n > x:
        n -= x
        x *= 2
    if n == 0:
        return print('e')

    y = (n-1) // (x // 5)
    print(a[y])






def main():
    n, = RI()
    solve(n)


if __name__ == '__main__':
    # testcase 2个字段分别是input和output
    test_cases = (
        (
            """
1
""",
            """
a
"""
        ),
        (
            """
8
""",
            """
a
"""
        ),
    )
    if os.path.exists('test.test'):
        total_result = 'ok!'
        for i, (in_data, result) in enumerate(test_cases):
            result = result.strip()
            with io.StringIO(in_data.strip()) as buf_in:
                RI = lambda: map(int, buf_in.readline().split())
                RS = lambda: buf_in.readline().strip().split()
                with io.StringIO() as buf_out, redirect_stdout(buf_out):
                    main()
                    output = buf_out.getvalue().strip()
                if output == result:
                    print(f'case{i}, result={result}, output={output}, ---ok!')
                else:
                    print(f'case{i}, result={result}, output={output}, ---WA!---WA!---WA!')
                    total_result = '---WA!---WA!---WA!'
        print('\n', total_result)
    else:
        main()

四、4724. 靓号

链接: 4724. 靓号

1. 题目描述

在这里插入图片描述

2. 思路分析

二分然后构造答案

  • 先计数找出最多的那个数的次数,记为mx,如果mx>=k,则直接返回不用花费任何。
  • 我们定义calc(x)为花费x及以上是否能改成靓号,显然这个是具有单调性的,可以二分一下,求出最小x。
  • calc的实现可以枚举i∈{0-9},尝试把其它数字改成i,这里贪心一下,由于花费是两数之差,因此顺序一定是从i向左右两端扩展来优先获得最小花费。
  • 构造答案是最费劲的,当我们知道最小花费是mn后,可能存在多种构造方式满足最小花费,但如何取最小呢。
  • 依然枚举i∈{0-9},尝试把其它数字改成i,然后比较10个答案中的字典序最小的那个。
  • 对特定的i,修改其它数字j时,要遵循一个原则,先修改比它大的j,从左到右;后修改比它小的j,从右向左。
  • 因为:
    • 如果j<i,修改j显然会使字典序变大。
    • 如果j>i,修改j显然会使字典序变小。

3. 代码实现

import sys
from collections import *
from contextlib import redirect_stdout
from itertools import *
from math import sqrt
from array import *
from functools import lru_cache
import heapq
import bisect
import random
import io, os
from bisect import *

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')

MOD = 10 ** 9 + 7


def my_bisect_left(a, x, lo=None, hi=None, key=None):
    """
    由于3.10才能用key参数,因此自己实现一个。
    :param a: 需要二分的数据
    :param x: 查找的值
    :param lo: 左边界
    :param hi: 右边界(闭区间)
    :param key: 数组a中的值会依次执行key方法,
    :return: 第一个大于等于x的下标位置
    """
    if not lo:
        lo = 0
    if not hi:
        hi = len(a) - 1
    else:
        hi = min(hi, len(a) - 1)
    size = hi - lo + 1

    if not key:
        key = lambda _x: _x
    while size:
        half = size >> 1
        mid = lo + half
        if key(a[mid]) < x:
            lo = mid + 1
            size = size - half - 1
        else:
            size = half
    return lo


def solve(n, k, s):
    s = list(map(int, s))
    cnt = Counter(s)
    mx = max(cnt.values())
    if mx >= k:
        return print(f"0\n{''.join(map(str, s))}")
    poses = [[] for _ in range(10)]
    for i, v in enumerate(s):
        poses[v].append(i)

    # 花x是否能搞出k个相同
    def calc(x):
        def f(i):
            cost = 0
            remain = k - cnt[i]
            for j in range(1, 10):
                if remain <= 0: break
                for p in i - j, i + j:
                    if 0 <= p <= 9:
                        c = min(cnt[p], remain)
                        cost += c * j
                        if cost > x: break
                        remain -= c
            return cost

        return any(f(i) <= x for i in range(10))

    mn = my_bisect_left(range(n * 10), True, key=calc)
    # DEBUG(mn)
    print(mn)

    def find(i):
        t = s[:]
        cost = 0
        remain = k - cnt[i]
        for j in range(1, 10):
            if remain <= 0:
                return ''.join(map(str, t))

            p = i + j
            if 0 <= p <= 9:
                ps = poses[p]
                c = min(cnt[p], remain)
                cost += c * j
                for x in range(c):
                    t[ps[x]] = i
                if cost > mn: break
                remain -= c
            p = i - j
            if 0 <= p <= 9:
                ps = poses[p][::-1]
                c = min(cnt[p], remain)
                cost += c * j
                for x in range(c):
                    t[ps[x]] = i
                if cost > mn: break
                remain -= c
        if remain <= 0:
            return ''.join(map(str, t))
        return 's'
    # for i in range(10):
    #     DEBUG((i,find(i)))
    print(min(find(i) for i in range(10)))


def main():
    n, k = RI()
    s, = RS()
    solve(n, k, s)


if __name__ == '__main__':
    # testcase 2个字段分别是input和output
    test_cases = (
        (
            """
6 5
898196
""",
            """
4
888188
"""
        ),
        (
            """
3 2
533
""",
            """
0
533
"""
        ),
        (
            """
10 6
0001112223
""",
            """
3
0000002223
"""
        ),
        (
            """
3 2
531
""",
            """
2
331
"""
        ),
    )
    if os.path.exists('test.test'):
        total_result = 'ok!'
        for i, (in_data, result) in enumerate(test_cases):
            result = result.strip()
            with io.StringIO(in_data.strip()) as buf_in:
                RI = lambda: map(int, buf_in.readline().split())
                RS = lambda: buf_in.readline().strip().split()
                with io.StringIO() as buf_out, redirect_stdout(buf_out):
                    main()
                    output = buf_out.getvalue().strip()
                if output == result:
                    print(f'case{i}, result={result}, output={output}, ---ok!')
                else:
                    print(f'case{i}, result={result}, output={output}, ---WA!---WA!---WA!')
                    total_result = '---WA!---WA!---WA!'
        print('\n', total_result)
    else:
        main()

六、参考链接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值