Official
A - Grandma's Footsteps Editorial
by
A - Grandma's Footsteps Editorial
by
sheyasutaka
実装方針
走る速度は毎秒 \(S\) メートルで一定なので,走る秒数を求めてから \(S\) 倍すれば答えになります.
シミュレーション解法
開始時点の状態を「\(0\) 秒続けて走っている」,走った累計秒数を \(0\) で初期化し,\(1\) 秒ごとに状態を更新するシミュレーションを行うことで,走る累計秒数を数えることができます.
各更新では,以下のような処理を行います.
- 今の状態が「走っている」なら,走った累計秒数を \(1\) 増やす.
- 続けて走っている秒数を \(1\) 増やす.その後,以下の変更を行う.
- 状態が「\(A\) 秒続けて走っている」なら「\(0\) 秒続けて止まっている」に変える.
- 状態が「\(B\) 秒続けて止まっている」なら「\(0\) 秒続けて走っている」に変える.
より簡潔な解法
\(A+B\) 秒ごとに同じ動作を繰り返すので,\(X\) 秒間は \(\lfloor \frac{X}{A+B} \rfloor\) 回の反復と \(X \bmod (A+B)\) 秒のあまりに分割できます(\(\lfloor \frac{X}{A+B} \rfloor\) と \(X \bmod (A+B)\) はそれぞれ,\(X\) を \((A+B)\) で割った商とあまりを表す).
各反復は \(A\) 秒の走りと \(B\) 秒の静止からなるので,反復する部分では合計で \(A \times \lfloor \frac{X}{A+B} \rfloor\) 秒走ります.
あまりの部分を \(m\) 秒とおくと,このあいだにおける走る秒数は,以下のように場合分けして求めることができます.
- \(m \leq A\) のとき,走る秒数は \(m\) 秒.
- \(m > A\) のとき,走る秒数は \(A\) 秒.
以上の \(2\) つを足し合わせることで,\(X\) 秒全体における走る秒数が求まります.
実装例 (C++)
\(1\) 秒ごとにシミュレートする解法は以下のように書けます.
#include <iostream>
using std::cin;
using std::cout;
using std::min;
int main (void) {
int s, a, b, x;
cin >> s >> a >> b >> x;
int len = 0;
int mode = 0, cnt = 0; // mode 0: run, mode 1: stop
for (int i = 0; i < x; i++) {
if (mode == 0) len++;
cnt++;
if (mode == 0 && cnt == a) {
mode = 1;
cnt = 0;
} else if (mode == 1 && cnt == b) {
mode = 0;
cnt = 0;
}
}
int ans = len * s;
cout << ans << "\n";
return 0;
}
算数的に解く解法は以下のように書けます.
#include <iostream>
using std::cin;
using std::cout;
using std::min;
int main (void) {
int s, a, b, x;
cin >> s >> a >> b >> x;
int len = 0;
len += (x / (a+b)) * a; // repeats (a+b) seconds
len += min(x % (a+b), a); // remainder
int ans = len * s;
cout << ans << "\n";
return 0;
}
posted:
last update:
