题解:洛谷P9948 [USACO20JAN] Race B

· · 题解

题解:洛谷P9948 [USACO20JAN] Race B

蒟蒻第一篇题解,看题面点这里

题目大意:

Bessie 以 0 米每秒的起始速度,用整数秒时间跑 K 米,每秒可以将速度增加 1 米、保持或减少 1 米,在终点时速度不超过 X 米每秒。计算对于 N 个不同的 X 值,跑完的最短时间。

普通版思路:

这道题的分我们一步一步拿。

首先,如果她一直加速,最后速度可能也没有超过 X,因此我们先算出直线加速到终点时的速度:

  while(MIN<k)
  //如果MIN小于k则将MIN加上i,最后将MIN的值重新赋为i-1。
  {
      MIN+=i;
      i++;
  }
  MIN=i-1;

分数到账。 然后我们定义一个函数 time 来处理其他情况:

int time(int a)
{
    if (a>=MIN) return MIN;
    int num=(a-1)*a/2;
    int sum=0;
    t=a;
    while(1)
    {
        sum+=t;
        if(num+(sum-t)*2+t>=k)
        {
            ans=a-1+(t-a)*2+1;
            /*题目要求, Bessie 的速度不能超过 X ,
            所以需要将速度从 t 降低到 t-1 ,再降低到 t-2 ,直到降低
            a。所以最小时间为 a-1+(t-a)*2+1 。*/
            return ans;
        }
        if(num+sum*2>=k)
        {
            ans=a-1+(t-a+1)*2;
            /*此时 Bessie 的速度可以保持不变,
            最小时间为 a-1+(t-a+1)*2 。*/
            return ans;
        }
        t++;
    }
}

代码分析:

num=(a-1)*a/2,----什么意思呀?

if(num+(sum-t)*2+t>=k), ----为什么这么写啊?

if(num+sum*2>=k),----看不懂怎么办?

首先,第一段代码的作用是计算 Bessie 跑完 a 米时的最小时间。

接下来,通过不断增加 $t$ 的值,$sum$ 。在每次循环中,判断根据当前累加和和已知的 $num$ 值,是否满足条件: - 如果 `num+(sum-t)*2+t>=k`,表示在当前累加和的基础上继续增加 $t$ 的值,加上前面的累加和,可以超过或等于 $k$ 。那么此时的最小时间 $ans$ 等于 `a-1+(t-a)*2+1`,**即当前 $a$ 米距离的最小时间再加上后面 `t-a` 米距离的最小时间再加上 $1$ 秒**。(因为在尝试增加 $t$ 的值之后,Bessie 可以选择增加速度使得总时间不变)。 - 如果 `num+sum*2>=k`,表示在当前累加和的基础上继续增加 $t$ 的值,可以超过或等于 $k$ 。那么此时的最小时间 $ans$ 等于 `a-1+(t-a+1)*2`,**即当前 $a$ 米距离的最小时间再加上后面 `t-a+1` 米距离的最小时间**。这里不需要额外增加 1 秒,因为在尝试增加 $t$ 的值之后,Bessie 不能再增加速度。 ------------ 好了,最后主函数直接不断输入输出就行了! ## 核心代码: ```cpp signed main() { // using namespace std; /*-------------关闭同步流-------------*/ std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); /*------------------------------------*/ cin>>k>>n; int i=1; while(MIN<k)/*如果MIN小于k则将MIN加上i,最后将MIN的值重新赋为i-1。*/ { MIN+=i; i++; } MIN=i-1; FOR(i,1,n) { cin>>x; cout<<time(x)<<endl; } return 0; } ``` ------------ 以上就是本题的**基本思路**,但一些大佬会觉得这题解~~太水了,又唠叨,~~ 不严谨,那么...... ## 数学版思路 **思维难度有点大** **可以跳过!** 对于每个固定的 $X$,Bessie 想要花费恰好整数秒完成比赛,因此可以考虑使用数学方法进行求解。 首先考虑当速度为 $t$ 时,Bessie 跑了多少米。在第 $i$ 秒,她的速度为 $v_i$,那么她跑的距离为 $v_1+v_2+...+v_i$ 米。显然,$v_1=0$,因此 $v_2=v_3=...=v_{t+1}=1,v_{t+2}=v_{t+3}=...=v_{2t}=2$,以此类推,$v_{(k-1)t+1}=v_{(k-1)t+2}=...=v_{kt}=t$。 可以发现,当速度为 $t$ 时,经过 $t-1$ 秒后 Bessie 的速度从 $0$ 增加到 $t$,并且跑了 $\frac{(t-1)t}{2}$ 米;经过 $t$ 秒后,Bessie 的速度保持不变,跑了 $t^2$ 米;经过 $t+1$ 秒后,Bessie 的速度从 $t$ 减少到 $t-1$,并且跑了 $t^2+t$ 米;经过 $t+2$ 秒后,Bessie 的速度从 $t-1$ 减少到 $t-2$,并且跑了 $t^2+2t$ 米,以此类推。 因此要求出 Bessie 在速度为 $t$ 时,第 $k$ 米的位置。当 Bessie 的速度在 $[1, t]$ 区间内逐渐增加时,她跑的距离为 $\frac{(t-1)t}{2}+(t^2)+(t^2+t)+...+[t^2+(k-(t-1)t-1)t]$,即 $\frac{(t-1)t}{2}+t^2(\lfloor\frac{k}{t}\rfloor-t+\frac{2}{t})+\frac{(k-(t-1)t-1)(k-(t-1)t)}{2}$ 米。 当 Bessie 的速度在 $[t, X]$ 区间内保持不变时,她跑的距离为 $\frac{(t-1)t}{2}+t^2(\lfloor\frac{k}{t}\rfloor-t+1)$ 米。 最后再考虑当速度为 $t-1$ 时,Bessie 跑了多少米。速度为 $t-1$ 时,当 Bessie 跑完 $k$ 米时,她的速度为 $t$,因此可以使用之前的公式计算。但是需要注意的是,在速度从 $t-1$ 降低到 $t$ 的时刻,Bessie 的速度必须小于等于 $X$,因此需要将速度从 $t$ 降低到 $t-1$,再降低到 $t-2$,直到降低到 $a$。因此最小时间为 $a-1+(t-a)\times2+1$。 ## 完结撒花!Bye!