赞
踩
只能想到纯纯暴力,枚举每一个数,统计每个数是否包含2023。
注意要算的是完全不包含2023的数目,别算反了。
答案:85959030
# 完全不包含2023 def judge(x): li = [3,2,0,2]; i=0 while x>0: t = x%10; x//=10 if t==li[i]: i+=1 if i==4: return 0 return 1 if __name__=='__main__': st = 12345678; ed = 98765432 res = 0 for x in range(st, ed+1): res += judge(x) print(res) # 85959030
能暴力出结果,但是我考虑错了。
我们要计算的是,任意次兑换后,某种硬币的数目达到最大。那么容易想到,只有把所有能兑换过去的硬币全部兑换过去,得到的目标硬币数才可能最大。
假设我们的目标硬币是面值为5(奇数),初始硬币数为5,并且面值分别为1+4、2+3的硬币可以兑换过来。假设目标硬币面值为4(偶数),初始硬币数为4,面值分别为1+3、2+2的硬币可以兑换过来。综上,我们可以枚举所有可能的目标硬币情况,对每一个面值的硬币分奇偶讨论他的最大数目,然后求出所有硬币的 max 值。
比赛时,我认为目标硬币面值的情况为1~2023,其实是想错了。应该是1–2023*2。要注意一点,当目标硬币的面值超过2023后,兑换前要考虑是不是coin1和coin2都有旧版硬币。
答案:682425
def calcu(x): cnt = 0 if x<=2023: cnt=x if x%2>0: # 奇数 for i in range(1, x//2+1): if x-i<=2023: cnt += i else: for i in range(1, x//2): if x-i<=2023: cnt += i if x//2<=2023: cnt += x//4 return cnt if __name__=='__main__': res = 0 for k in range(1,2023*2+1): res = max(res, calcu(k)) print(res) # 682425
这是一道线性dp题。考试时,我写了个二重循环(虽然也是dp的思想),估计只能过50%左右。
令f[i]
表示以a[i]
结尾的子序列的最大价值,由于松散子序列要求pi - pi-1 >= 2
,所以f[i] = max(f[j]) + a[i]
,j从0 ~ i-2
。最后答案是遍历所有f[i]
,找一个最大值。
这样写是一个二重循环,肯定会超时,所以要优化代码。我们发现f[i-2]
一定大于f[i-4]
,且f[i-3]
一定大于f[i-5]
,因此内层循环可以转化成只比较f[i-2]
和f[i-3]
的大小。
if __name__=='__main__':
s = input(); l = len(s)
f = [0]*(l+5)
for i in range(l):
if i-2>=0: f[i] = max(f[i], f[i-2])
if i-3>=0: f[i] = max(f[i], f[i-3])
f[i] += ord(s[i])-ord('a')+1
res = 0
for i in range(l):
res = max(res, f[i])
print(res)
这是一道二分+区间合并的题目,但是鼠鼠想不出来,听了y哥的点拨写的。
二分法可以找到区间的边界点,如果我们以时间为轴,右侧区间的时间点满足管道中每一段中间的传感器都检测到有水流,左侧区间的时间点是管道中每一段中间的传感器不能都检测到水流,所以本题的要求就是求出右区间的边界点。二分法有很多需要注意的细节,所以我就直接背模板了。
在二分法里,对于每一个时间点,我们都要判断此时是否满足区间性质。可以算出该时间点,每一个阀门喷出的水能覆盖多长的区间。用区间合并算法合并这些区间,然后判断最后得到的区间是不是能覆盖所有的传感器。
要注意这题在区间合并部分不需要排序,如果加上排序,区间合并部分的时间复杂度就是 O ( n l o g n ) O(nlogn) O(nlogn),在new online judge上测会有一个样例超时。如果不排序的话,区间合并在模板的基础上就要改,不能有区间数目cnt的统计情况。因为题目里说 L i − 1 < L i L_{i-1}<L_i Li−1<Li,所以是可以证明不需要排序的。但鼠鼠就不写了。
# 二分+区间合并 def check(t, l): # 区间合并 le = len(li); ed = 0 for i in range(le): if t-si[i]>=0: a = max(li[i]-t+si[i], 1); b = min(li[i]+t-si[i], l) if a<=ed+1: ed = max(ed, b) if ed==l: return True else: return False if __name__=='__main__': n, ll = map(int, input().split()) li, si = [], [] for _ in range(n): li_, si_ = map(int, input().split()) li.append(li_); si.append(si_) # 二分 l, r = 0, int(2e9) while l<r: mid = (l+r)//2; if check(mid, ll): r=mid else: l=mid+1 print(l)
想了个bfs的写法,但是只过了一个样例。网上也找不到题解,放弃了。
以为自己省赛写对了,结果发现只过了一个样例。或许省赛我只有10多分吧。
国赛考完了,以后有机会再填坑。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。