解题思路:
先说几句闲话:
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分
7 人评分
1908题解浏览:680 |
关于C语言变量位置的问题浏览:294 |
1050题解(结构体数组与结构体指针的使用)浏览:1216 |
2003年秋浙江省计算机等级考试二级C 编程题(1) (C语言代码)浏览:567 |
IP判断 (C语言代码)浏览:592 |
字符串比较 (C语言代码)浏览:770 |
1052题解(链表操作)浏览:782 |
C语言程序设计教程(第三版)课后习题5.4 (C语言代码)浏览:501 |
A+B for Input-Output Practice (I) (C语言代码)浏览:598 |
快速排序算法1浏览:996 |