人間だけど競プロやる

解けなかった問題を理解できたら記事を投稿します。日本語の解説が見つからなかったもの中心。

Codeforces Round #673 (Div. 2)


C. k-Amazing Numbers

添字と境界条件の扱いがめんどくさい問題。
気づき

  • 範囲を全部試すのは無理
  • ある値を選んだとき、全体を覆うのに必要な最短の範囲を求めることができる
f:id:bqn2:20200929131224p:plain
fig.1


現れる数字は1からNまでしかないので、順番にどれだけの範囲があれば全体をカバーできるかをもとめて、範囲の長さ1からNまで出力すれば良い。

解法

  1. 同じ数字が現れるインデックスを求める
  2. 数字ごとに全体をカバーするのに必要な最小の範囲を求める(一個前(と先頭と終端)のインデックスとの差のmax)
  3. 同じ範囲の大きさが必要な場合、数字が小さいほうが優先

という処理で B[範囲の大きさ] = 数字 の配列を作って順番に出力すれば良い。

D. Make Them Equal

Cより簡単では疑惑
この手の問題を見たときはまず確認することがあって、

  1. 不変量に注目する

問題の操作をみると、同じ値を「足して」「引いて」いるから、全体の合計は変わらないことがわかる。
こういった不変量に注目すると問題がみえてくることがある。
今回は、合計がかわらないという条件で全体を等しくするので、それぞれは\frac{sum}{N}で等しくなってそれ以外にない。
あとは、「1 \times x」での操作が最も柔軟性が高いことにきづければ、なるべくインデックス1に移動させてから、それぞれのインデックスに、\frac{sum}{N}ずつ分配すれば良いことに気づく。
また、(インデックス1から順番に操作できるとは限らないが)、N \times 2回あれば、全体をインデックス1に移動できることもわかる。

解法

  1. sumを配列aの合計とする
  2. a_iiで割り切れるならa_1に移動する(a_iからa_iを引いて、a_0a_iを足す)
  3. a_iiで割り切れないなら、m=i - (a_i \mod i) をインデックスmかインデックス1から移動して加算することで、iで割り切れるように調節する(そして2の操作)
  4. a_1がsum、a_2からa_Nが0になる
  5. a_1から各インデックスへ\frac{sum}{N}ずつ移動する

a_1に集めるのにN \times 2回、a_1から分配するのにN回で、合計N \times 3回に収まる。