Codeforces Round #702 (Div. 3)のきろく
参加はしていないですが、全問解いたので書いていきます。問題文和訳はこちら
- A. Dense Array / Плотный массив
- B. Balanced Remainders / Сбалансированные остатки
- C. Sum of Cubes / Сумма кубов
- D. Permutation Transformation / Трансформация перестановки
- E. Accidental Victory / Случайная победа
- F. Equalize the Array / Уравняй массив
- G. Old Floppy Drive / Старый дисковод
- 結果、感想
A. Dense Array / Плотный массив
各 に対して と の間に を挿入することで密な配列を作ることができます。挿入する数を とすると $$2^{m_i} \min\{a_i,\,a_{i+1}\} \lt \max\{a_i,\,a_{i+1}\} \leq 2^{m_i+1} \min\{a_i,\,a_{i+1}\}$$
であり、 が整数であることから で、答えはこれの和となりますが、 の値を直接計算すると誤差が出てくる可能性があるためお勧めしません。最悪ケースの場合でも であるため、実際に挿入する数を計算しても十分間に合うため、そちらで実装する方が良いでしょう。
B. Balanced Remainders / Сбалансированные остатки
を 増やすという操作は、 を 減らし を 増やすという操作と等価です。
となるとき です。そうではない場合、 となる が存在します。そのような について過剰分を に移してやるという操作を繰り返すことで、 にすることができます。
C. Sum of Cubes / Сумма кубов
となるので、 について から 内の範囲で全探索します。 については が立方数であるかを確かめなければなりませんが、 としても一般性を失わず、各 について の値をstd::set
やstd::unordered_set
等に記憶させておけば簡単に調べることができます。
D. Permutation Transformation / Трансформация перестановки
の部分列から根の深さ の部分木を構成するとき、 とすると であり、 と の部分木から根の深さ の部分木をそれぞれ構成させるので、再帰関数によって実際に1つずつ求めてやることによって答えを作ることができます。
再帰関数の引数としては部分列の左端 、右端のインデックス *1や元の配列 、答えの保存用の配列 、現在の深さ が必要です*2。
E. Accidental Victory / Случайная победа
をソートした列を とすると、 のとき に対応する選手はそれより少ない選手全員と対戦した後にそれよりも に対応する選手には勝つことができます。このとき に対応する選手が優勝可能性がある場合、 に対応する選手も優勝する可能性があることが分かります。よって、トークンが少ない方から累積和をとって次の選手を倒すことができるかを保存していき、トークンが多い方から優勝可能性があるかを調べていくことで答えが求まります。優勝可能性のある選手の番号を出力する必要があるのでソートする際はstd::pair
などで選手の番号も保存するようにしましょう。
F. Equalize the Array / Уравняй массив
内で が登場する回数を と書くことにし、 とします。 内の要素を小さい順に とします。 の値を1つ決めたとき答えは $$\displaystyle\sum_{c_x \lt C}\, c_x + \sum_{c_x \geq C}\, (c_x - C)$$ となります。これを とします。
のときは最小値を与えません。というのも、 のときは となりますし、 のときは となるからです。
さて が の要素を小さい順に遷移していくときの状態遷移を見ていきましょう。 から に移るとします。 とします。このとき は だけ増え、 は だけ減ります。依って の和を利用することに依って から各 を求めればいいと分かります。
また、解説のコードは $$\displaystyle\sum_{c_x \lt C}\, c_x + \sum_{c_x \geq C}\, (c_x - C) = \sum_{c_x \lt C}\, c_x + \sum_{c_x \geq C}\, c_x - C \sum_{c_x \geq C}\, 1$$ より を遷移させているようです。
G. Old Floppy Drive / Старый дисковод
とします。
のとき、和は に達することなく1周しますが、そのとき初期状態よりも減った状態で和を再び取り始めるので 以上になることはなく、永遠に動き続きます。
そうでないとき、フロッピーディスクはいつかは止まります。
のとき、 となるような を用意しておくことで 内の 以上となる1番左の要素を 内での二分探索で探すことができます。そのような要素のインデックスから 引いた値*3が答えです。
のとき となり、一周するごとに初期和が 増えていくので、 が成立する最小の 即ち、 回廻した時上の、 の場合に帰着させることができます。
結果、感想
Div. 3というのもあって簡単目の問題でした。ただ、実際に出てたらFやGのコーナーケース等に苦しめられてたかもしれません。
AからCの問題文に形式的には(formally)という言葉が含まれているのが面白いなと思いました。