2020.2.25GDUT寒假训练排位赛3-D

D — Race

题目大意:

贝西正在进行一场长度为K(1≤K≤109)米的赛跑。她刚开始以每秒0米的速度跑。在给定的一秒内,她可以把速度提高1米/秒,或者保持不变,或者降低1米/秒。例如,在第一秒,她可以把速度提高到1米/秒,然后跑1米,或者保持0米每秒,然后跑0米。贝西的速度永远不会降到0以下。
贝西总是跑向终点线,她希望在整数秒后完成(在这个整数秒内结束或超过终点线)。此外,她不想在终点线跑得太快:在贝茜跑完K米的那一刻,她希望她的速度不超过每秒X米(1≤X≤105)。贝西想知道当N(1≤N≤1000)个不同的X值时,她能多快跑完比赛。
输入
第一行包含两个整数K和N。
接下来的N行各包含一个整数X。
输出
输出N行,每行包含一个整数,表示贝西刚跑过终点时速度不大于X所需的最短时间。
在这里插入图片描述

题目分析:

想要时间最短,肯定是一直提升速度,那么就有两种情况发生:
(1) 提升速度还没到达x,路程已跑完。这时最短时间就是(最大速度时+是否有剩余路程(1 or 0) )。
例如:k=11,x=5
速度持续提升到4时,路程走了10,不能再提升到5,那么最大速度为4。这个剩余1的路程可以在速度为1时走多1秒(如果剩余2则在速度2多走1秒,以此类推)。
(2) 提升速度到了x,路程还没有走完。那么过程中速度时先增后减的变化,最短时间肯定是开始时尽量提速,后面尽量刚好以速度x过终点。欸,假设跑过终点后继续持续减速跑直到速度0,那么这个速度变化就像是对称的(当然,也可以减去前面x-1速度的路程,假设起点速度为x)。
例如:k=10,x=3 答案的速度依次为 1 1 2 3 3
依据上面思想,加上终点后的速度为 1 1 2 3 3 2 1(走完1速度即0),加上的那些速度走了3米
移动某几个速度变为 1 2 3 1 3 2 1,提升的最大速度为3,1到3走了6的路程,由于对称,1到3,3到1,共12米,减去加上去的3米,也就是9米,还有1米路程,这1米就是在速度为1时多走1秒。

代码实现:

#include <iostream>
#include <cstdio>
using namespace std;

typedef long long LL;
LL k;
int n,x;
LL lj[100007];  //lj[i] 1到i的累加

void init()
{
    lj[0] = 0;
    for(int i=1; i<100003; i++)
    {
        lj[i] = lj[i-1]+i;
    }
}

int main()
{
    init();
    scanf("%lld%d",&k,&n);
    for(int i=0; i<n; i++)
    {
        int ans = 0;
        scanf("%d",&x);
        if(lj[x]>=k)    //速度提升到x时跑完
        {
            for(int j=1; lj[j]<=k; j++) ans = j;    //未跑过终点的最大速度
            LL bbb = k-lj[ans]; //剩余路程
            if(bbb>0) ans = ans+1; //没有刚好跑完,则在中间多一秒
            printf("%d\n",ans);
        }
        else            //速度提升到x时还没到终点
        {
            LL ker = k+lj[x-1]; //加上假设跑过终点后减速到0的路程
            for(int j=1; lj[j]*2<=ker; j++) ans = j;    //提升的最大速度
            LL aaa = ker-lj[ans]*2LL;   //剩余路程
            if(aaa==0LL) ans = 2*ans-(x-1); //刚好跑完,减去跑过终点后的时间
            else if(aaa<=ans*1LL+1) ans = 2*ans-(x-1)+1;    //不超过最大速度+1,减去跑过终点后的时间,加上1秒
            else ans = 2*ans-(x-1)+2;   //超过最大速度+1,不能1秒跑完,所有加2秒
            printf("%d\n",ans);
        }

    }

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值