解题思路:
先说几句闲话:

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.0分

5 人评分

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

评论列表 共有 0 条评论

暂无评论