解题思路:
先说几句闲话:
dotcpp的数据还是强啊,我第一次的代码 蓝桥杯大赛官网 直接满分通过了,结果来这就40多分!!!
分数低是因为没有考虑到(所有技能加点次数和)都达不到题目要求的技能升级次数m次!二分出来的结果是空的!!!给我整笑了,太牛了!!!
为什么后面要写getV()和check()两个函数,因为我们的目的是(求和)而不是求最后的一次技能点(写一个函数同时计算(技能和)和(升级次数)会大大增加时间),最后强调二分计算过程只是帮我们求出最后一次技能点是多少!!!最后再用二分出来的答案套进去求和,这样就一次的过程!!!
注意事项:
题目很简单,就是类似二分答案的灵活运用,加点数学求等差数列和,O(1)计算
参考代码:
n,m=map(int,input().split())
list1=[]
for i in range(n):
list1.append(list(map(int,input().split())))
def getV(mid):# 最后的求技能和
dot,v=0,0
for i in list1:
a,b=i
dot0=0
if mid<=a: # 保证技能点不大于最大的提供技能
dot0+=1
m=(a-mid)//b
dot0+=m # 线性方程推导 单纯就是数学的一元一次函数
dot+=dot0
# 累加技能点
last=a-m*b # 用数学的线性函数求最后一个技能点的位置!!
v+=(a+last)*(m+1)//2 # 等差数列求和
return dot,v
def check(mid):
dot=0 # 统计升级的次数
for i in list1:
a,b=i
dot0=0
if mid<=a: # 保证技能点不大于最大的提供技能
dot0+=1
dot0+=(a-mid)//b # 线性方程推导 单纯就是数学的一元一次函数
dot+=dot0
return dot>=m
left=1
right=10**6
result=[]
while left<=right:
mid=(left+right)>>1
if check(mid): # 足够 需要增加最后一次技能
left=mid+1
result.append(mid)
else:
right=mid-1
# 获取到的答案可能最后dot和m不相等 毕竟存在很多相同的技能点,这里我们求(最后的一次技能点+1)得到的技能次数,再弥补上剩余的,显然就是乘法
# 答案需要考虑result为空的情况 也就是所有点加起来都达到不m 笑垃了,什么数据
if result!=[]:
mmax=max(result)
d,v=getV(mmax+1)
print(v+mmax*(m-d)) # 弥补剩余的差多少mmax,就乘上多少!! 不解释了,自己体会把!!!!
else:
d,v=getV(1) # 所有技能点都考虑进去 全部!!!我滴妈呀
print(v)
0.0分
5 人评分
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
发表评论 取消回复