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

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

AtCoder ABC 046 C - AtCoDeerくんと選挙速報 (ARC 062 C) (4Q, 水色, 300 点)

問題文の理解が大変かもしれない

問題概要(意訳)

2 つの正の整数  t, a を次のように  N 回更新していく。最初、 t = a = 1 である。


 i 回目の更新では 2 つの互いに素な正の整数  T_{i}, A_{i} が与えられるので、

  •  X \ge t
  •  Y \ge a
  •  X : Y = T_{i} : A_{i}

を満たすような 2 つの正の整数  X, Y を 1 つ求めて、 t, a をそれぞれ  X, Y に置き換える。


最終結果における  t + a の値の最小値を求めよ。

制約

  •  1 \le N \le 1000
  •  1 \le T_{i}, A_{i} \le 1000

考えたこと

単純に、毎回  X, Y の値をできるだけ小さく抑えるようにすればよい。そのためには

  •  T_{i} x \ge t
  •  A_{i} y \ge a

を満たすような最小の  x, y を求めて、次のようにすればよい。

  •  t T_{i} \times \max(x, y) の値に置き換える
  •  a A_{i} \times \max(x, y) の値に置き換える

毎回の処理は  O(1) の計算量で実行できるので、全体の計算量は  O(N) となる。

コード

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

int main() {
    long long N, T, A, res_t = 1, res_a = 1;
    cin >> N;
    for (int i = 0; i < N; i++) {
        cin >> T >> A;

        // Tx >= res_t, Ay >= res_a を満たす最小の x, y を求めて、その最大値をとる
        long long x = (res_t + T - 1) / T;
        long long y = (res_a + A - 1) / A;
        res_t = T * max(x, y), res_a = A * max(x, y);
    }
    cout << res_t + res_a << endl;
}