けんちょんの競プロ精進記録

競プロの精進記録や小ネタを書いていきます

AtCoder ABC 249 A - Jogging (6Q, 灰色, 100 点)

1 秒ごとにシミュレーションする方法と、数学的に 2 人の休憩時間をそれぞれ求める方法とがある。どちらもできるようにしておきたい! ここでは、数学的に処理する方法を書く。

問題概要

高橋君は「 A 秒間秒速  B メートルで歩き、 C 秒間休む」ことを繰り返す。

青木君は「 D 秒間秒速  E メートルで歩き、 F 秒間休む」ことを繰り返す。

二人が同時にジョギングを始めてから  X 秒後、高橋君と青木君のうちどちらが長い距離を進んでいるか?

制約

  •  1 \le A, B, C, D, E, F, X \le 100

考えたこと

高橋くんについてのみ考えれば、青木くんは同様である。よって、高橋くん飲み考えよう。

まず、高橋くんの行動は  A + C 秒ごとに同じ動きを繰り返すことに注意しよう。同じ動きが繰り返される問題においては

  • 何回繰り返されるのか
  • その後、何秒余るのか

を求めることが肝要となる。ここでは、 X A + C で割った商を  q、余りを  r としよう。このとき、


  • 高橋君は「 A 秒間秒速  B メートルで歩き、 C 秒間休む」ことを  q 回繰り返したのちに
  •  r 秒余る

となる。残る問題は

  • 1 回の繰り返しで、何メートル進むか(それを  q 倍する)
  • 余った  r 秒で、何メートル進むか

を求めることである。

残りの問題

まず、高橋くんが 1 回の繰り返しで進む距離は、

 A \times B メートル

である。さらに、余った  r 秒で進む距離は、

  •  r \le A のとき: r \times B メートル
  •  r \gt A のとき: A \times B メートル

である。

答え

以上より、最終的に答えは


  •  r \le A のとき: (Aq + r)B メートル
  •  r \gt A のとき: (Aq + A)B メートル

となる。青木君についても同様である。ここで、高橋君・青木君についての答えを求める共通の処理を関数として切り出すと実装が明快になる。

コード

#include <bits/stdc++.h>
using namespace std;

// A 秒間秒速 B メートルで歩き、C 秒間休むことを X 秒間繰り返して進む距離
int calc(int A, int B, int C, int X) {
    int q = X / (A + C);
    int r = X % (A + C);

    if (r <= A) return (A * q + r) * B;
    else return (A * q + A) * B;
}

int main() {
    int A, B, C, D, E, F, X;
    cin >> A >> B >> C >> D >> E >> F >> X;

    int taka = calc(A, B, C, X);
    int aoki = calc(D, E, F, X);
    if (taka > aoki) cout << "Takahashi" << endl;
    else if (taka < aoki) cout << "Aoki" << endl;
    else cout << "Draw" << endl;
}