ABC166

昨日とまるっきり違うセットだったらしく、天才が無限人いるように感じられてワロタ。特に、DEを早解きできる人がここまで多いのは意味がわからない。体感で昨日よりそんなに悪い出来とも思えないが、青コーダーにとっては全完早解きセットだったわけで、スピードの差が出たということだろう(もちろん実力が高ければスピード関係なくいい順位が取れるけど、さすがにスピードをカバーできるほどの実力があるとは思っていない)。

A - A?C

夢のような問題設定ですね。stringで受け取って、s[1] ^= 'R' ^ 'B';として出力。

B - Trick or Treat

入力を受け取れますかという問題だなあ。長さNの配列を用意し、入力を受け取りながらお菓子を持っているすぬけ君にチェックを入れて、最後に数えればいい。すぬけ君がたくさんいるのけっこう混乱する。

C - Peaks

少し考えたけど、まあグラフとして受け取る。一本の道と一本道は違う。最近、天才系ではなく全探索系のCが多いね。

D - I hate Factorization

見た目がヤバい。しかも、「出力は○○以下の整数」とか書いてない。条件を満たせばどんなに大きな整数でもいいということだが、つまりそういう解は存在しないということか?焦る。まあよく考えるとiの5乗とi+1の5乗はiの4乗のオーダーの差があるので、でかい数は何と差を取ってもでかい(解はXと比べてそんなに大きくない)とわかる。差がXより大きくなったら不必要なので、そこで打ち切って候補のリストを作る。1000個もないので2乗の全探索でOK。符号がけっこうややこしいので不安だった。

これ落ち着いて考えるとただの全探索なんだよね。候補が1000個以下だとさえわかれば、ほんとに全探索するだけ。符号を考える必要もない。

E - This Message Will Self-Destruct in 5s

これは難しい。身長とか距離とか色々固定して考えてみるがどうにもならない。ただ、ある人とペアになれる相手の身長は遠くなるごとに1, 2, 3,...と増えていくと決まっている。また、右側だけを見ることにすれば絶対値を考える必要がない。つまり、A_iをA_i - iに置き換えることで、あとは右側にA_i - i == hogeとなるiの個数がわかればいいことになったり。しそうだ。A_i - iは負にもなるので配列でやるのは混乱しそう。普段使わないが、平衡二分探索木を使おう。set::multisetでいいかな。TLE。「は!?」声が出た。

慌てて調べると、multisetのcountの計算量は個数にも依存する。はい。よく理解してないうえに慣れないことをするもんじゃないね。定数倍が重いからなるべく使いたくなくて経験値がないんだよな。TLEはほんとに悔しい。std::mapに直してAC。左側を見ればよかったかな。あまりにも難しくてstd::vectorで済ます余裕がなかった。

F - Three Variables Game

これも入力受け取るのめんどいじゃん。sは2, 1, 0に変換して保存した。A, B, Cもa[3]にしたけど結局それを生かした実装はできなかった。少なくともただの貪欲(小さくないほうを減らす)はダメ。2^N回の選択をするというのはいかにもDPだが、状態が多すぎて間に合わない。ここで、碁石を使って考える。碁石を1つ移動させる操作と考えられる。これさあ、A, B, Cは10^9以下だけどN以下としても同じだよね、そして10個くらいまで減らしてもよくね?実行速度(使用メモリ)と実装のしやすさを勘案し、A, B, Cは6以下に切り詰め合計18個までの碁石が存在する前提でDPした。DPテーブルは(10^5+1)*(18+1)*(18+1)。あとはDPするだけ。実装がクソ面倒だけど。その状態に遷移可能なら、そこから到達できる場所(最大で2か所)を1にする。減らすやつが0より大きいことだけチェックすればいいというのが、さっき言った実装のしやすさ(18個以下しかないので19個以上になるかチェックする必要がない)。あとはそれを逆に辿って選択方法を構成する。ここも面倒。面倒な書き方しかできないの力不足だなあ。最低限きれいに書けてACできたのも実力ではあるけど。6個より多い部分は使わなくても大丈夫というのを、(実装する時間まで考えると全然時間もないので)証明せずに使っていたのでそこが不安だった(まあ長々と書いたコードも不安ではあるけど別物だよね)。これ解説PDFの方針を本番で見つけるの"強さ"が必要だなあ。俺はDPに逃げてしまうよ(ところでこういう典型DPだいぶ慣れたね)。