双十一CF必上1400


私信TA

用户名:dotcpp0602879

访问量:4059

签 名:

放纵是本性,克制是智慧。

等  级
排  名 408
经  验 5035
参赛次数 3
文章发表 22
年  龄 21
在职情况 学生
学  校 江南大学
专  业 软件工程

  自我简介:

蓝桥国一终归与我!

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

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 人评分

  评论区

  • «
  • »