[acwing周赛复盘] 第 71 场周赛-补20221023

本文复盘了ACwing第71场周赛,主要解析了三个算法问题:1.如何找到三个整数使得它们的和等于目标值;2.探讨整数拆分为质数的问题,基于哥德巴赫猜想;3.模拟糖果购买过程,计算购买糖果的最少次数。通过代码实现和思路分析,展示了问题的解决策略和复杂度分析。
摘要由CSDN通过智能技术生成

一、本周周赛总结

  • 没打,补一下题。
  • T1数学水。
  • T2哥德巴赫猜想。
  • T3循环模拟。

二、 4621. 三个整数

链接: 4621. 三个整数

1. 题目描述

在这里插入图片描述

2. 思路分析

  • 题目保证有解。
  • 因此让x,y尽量大,z尽量小即可。

3. 代码实现

import collections
import io
import os
import sys
from collections import deque

if sys.hexversion == 50923504:
    sys.stdin = open('input.txt')
    RI = lambda: map(int, input().split())
else:
    input = sys.stdin.readline
    input_int = sys.stdin.buffer.readline
    RI = lambda: map(int, input_int().split())

RS = lambda: input().strip().split()
RILST = lambda: list(RI())


if __name__ == '__main__':
    a,b,c,d = RI()
    print(b,c,c)

三、4622. 整数拆分

链接: 4622. 整数拆分

1. 题目描述

在这里插入图片描述

2. 思路分析

  • 哥德巴赫猜想,每个大于2的偶数可以下城2个质数之和。
  • 每个大于7的奇数可以写成3个奇质数之和。
  • 按照题目要求,使n拆分更少的数,且应当是质数使每个拆分贡献是1。
  • 分类讨论即可,看注释。

3. 代码实现

import collections
import io
import os
import sys
from collections import deque
from math import sqrt

if sys.hexversion == 50923504:
    sys.stdin = open('input.txt')
    RI = lambda: map(int, input().split())
else:
    input = sys.stdin.readline
    input_int = sys.stdin.buffer.readline
    RI = lambda: map(int, input_int().split())

RS = lambda: input().strip().split()
RILST = lambda: list(RI())

MOD = 10 ** 9 + 7


"""哥德巴赫猜想:任意大于5的整数都可以写成3个质数之和。n>5,当n是偶数,n=n-2+2,n-2也是偶数,可以分解成2个质数的和;当n是奇数,n=n-3+3,n-3是偶数
偶数的哥德巴赫猜想:任意大于2的偶数都可以写成2个质数之和;比如4=2+2,6=3+3,8=3+5;如果n>4,则可以分解成两个奇质数的和。
奇数的哥德巴赫猜想:任意大于7的奇数都可以写成3个奇质数之和;比如9=3+3+3,11=3+3+5,这是因为可以直接-3;7本身-3就是4了。
关于本题,分类讨论:
如果n是质数答案是1。
否则如果n是偶数,注意到这一步,偶数是从4开始的,那满足偶数的哥德巴赫猜想,因此可以分解成2个质数,这两个数的贡献分别是1,答案是2。
否则如果n是奇数,注意到这一步,奇数是从9开始的,则满足奇数的哥德巴赫猜想,因此可以分解成3个奇质数,答案最多是3;但是要先判断一下,如果n-2是质数,则可以分解成2和一个奇质数,答案是2
"""
def solve():
    n, = RI()
    def is_zhishu(x):
        for i in range(2, int(sqrt(x)) + 1):
            if x % i == 0:
                return False
        return True
    if is_zhishu(n):
        return print(1)

    if n & 1 == 0 or is_zhishu(n-2):
        return print(2)
    print(3)

if __name__ == '__main__':
    solve()

四、4623. 买糖果

链接: 4623. 买糖果

1. 题目描述

在这里插入图片描述

2. 思路分析

  • 直接while True模拟。难点在于计算复杂度保证能过。
  • 结论,一个数t对小于它的s取模,结果最多是t的一半。
  • 本题每次t%=s,因此在lgt的时间就可以降为0。
  • 整体复杂度O(nlgt)

3. 代码实现

import collections
import io
import os
import sys
from collections import deque
from math import sqrt

if sys.hexversion == 50923504:
    sys.stdin = open('input.txt')
    RI = lambda: map(int, input().split())
else:
    input = sys.stdin.readline
    input_int = sys.stdin.buffer.readline
    RI = lambda: map(int, input_int().split())

RS = lambda: input().strip().split()
RILST = lambda: list(RI())

MOD = 10 ** 9 + 7

"""
1. 模拟这个买糖果的过程,每次买一圈看看能买多少设为s,显然t>=s,那么一定可以转t//s圈,t本身减小到t%s;
2. 这里思考一下转t//s圈的前提是这几圈每圈数量不变:显然不会变大,因为上一圈没买到的贵的,下一圈钱也不可能够;也不会变小,因为t//s保证了每圈花的钱都可以是s。
3. 显然这几圈下来t%=s。对答案的贡献是圈数*买了几个糖:ans+=t//s*c
4. 计算一下复杂度,为什么不超时呢(n<2e5,t<1e18,1<=ai<=1e9)。
5. 显然循环内枚举每个店动作复杂度是O(n)。那么一共执行了多少次循环呢,观察退出循环的条件是s == 0。
6. s == 0只有一种可能,就是一圈店走下来,没有一个店<=t。则重点是t什么时候能降到足够小,即小于min(a)最差0。
7. 观察t的变化公式,每次t %= s。先说结论,t对一个小于t的数取模,t每次至少折半,因此复杂度是O(lgt),总体复杂度是O(n*lgt),lg1e18大概是63,因此不超时。
8. 证明为什么至少折半:
    我们知道s<=t, 等于的情况不说了,t%s=0。
                当s>=t//2, 即s在t一半的右边,t%s = t-s < t//2
                当s<=t//2, t//s >= 2,取模一定<s,显然小于t。
    因此t对小于t的数取模,至少折半 
"""
def solve(n, t, a):
    ans = 0

    while True:
        s = 0
        c = 0
        for x in a:
            if s + x <= t:
                s += x
                c += 1
        if s == 0:
            break
        ans += t // s * c
        t %= s
    print(ans)


if __name__ == '__main__':
    n, t = RI()
    a = RILST()
    solve(n, t, a)

六、参考链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值