[acwing周赛复盘] 第 71 场周赛-补20221023
一、本周周赛总结
- 没打,补一下题。
- 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)
六、参考链接
- 无