ARC117

いやあスピード。実力と言えばそれまでだけど。C好き。ギリギリでDが通ったので、EFは読めなかった。

A - God Sequence

1 2 3 4 -1 -2 -3 みたいに作って、合計が0にならないぶんは個数が少ないほうの絶対値最大の数を書き換える(1 2 3 4 -1 -2 -7 みたいにする)。実装にかなりてこずった。いい方法あったかなあ。

(解説を聞いて)いやいい方法はあるものだなあ。正の数の合計を100万にする方針でACしといた。

B - ARC Wrecker

大砲の効果がやや不自然だけど、だるま落としみたいになるイメージ。ソートしても答えは変わらない。2つのビルの高さの差が縮まることはあっても広がることはないとか考える。と、これは簡単で、段差毎に差を0からそのまままでのどれかを選ぶ操作になるので掛け算していけばいい。差がないときを場合分けしていたがどうせ1通りなのでそのままやればいい。高さ0の地面を追加すると実装が楽。

C - Tricolor Pyramid

規則を読むと、ちゃんと各色に対して対称になっている。文字に順番はないので適当に 0, 1, 2 の番号へ置換する。手で小さい例を色々試した。1個のブロックを変えたときの寄与を見ると、1増やすと上の段では1減る感じ。シェルピンスキーのギャスケットみたいのは出題されたことがあったので、この演算がどうなっているか考えるが、こういうのどうしたらいいんだろうね。とりあえず全部0の状態(答えは当然0)から1個ずつ変更していく方針がいけるタイプみたいなのでそれに決める。けっこうな時間を消費したのち、単にパスカルの三角形のmod 3で1段毎に符号反転だとわかった(mod 3はあまりに自然なのでそこを最初に決め打って修正していく感じでやるのがいいのかな結果論に思えるんだよなあ)。端も、同じ数が続いてると思えば特に関係ない。3は素数だしあとは計算するだけだが、なんかACLに怒られる。そうかmod 3はできない(3で割る操作とかあるので)。どうせN-1個の中からいくつか選ぶ話なので、素因数3の個数と(3で割れるだけ割ったときの)あまりを管理していけばよさそう(要するに3と3以外の素数に分けて掛けたり割ったりする)。かなり時間をかけてしまったが、サンプルが通り提出。

WAでかなりびっくりしたけど、コードをじっくり読み直すと、あまりの計算でオーバーフローしている。modintを捨てないほうがよかったのかなあ。でもまあこれはいいよ。単純ミスだし気づくのにそこまで時間かからなかった。そこまでのあらゆるステップに時間をかけているのが問題だ。疲れたので解説はあとで読む。

(追記)解説のmod 3で二項係数求める方法は自分がやったやつの一般化みたいのだった。それとは別にLucasの定理っていうのがあって、logが付くけど簡単に計算できるみたい。たしかにパスカルの三角形の5段目がみんな5の倍数なのは知ってたし、今回の問題で3冪段進むと端しか残らないという性質も関係してるんだなあ。

D - Miracle Tree

最大値を小さくしたい。最小値と最大値は直径の両端に置きたい気がする。なんかその端から順に流し込むだけでは?みたいになるがよく考えると枝分かれしてると全然ダメ。木がスターのときなんか相当大きな数が必要になる。いくつかの例を考えて、1個だけ長い枝を作るとどっちから番号を振るかで最大値が変わることに気づく。短いものからやるといいらしい。移動するたびにインクリメントしていくのも思いついて実装に入る。ここで、DFSの根の選び方がわからないことに気づく。最初に直径って言ったのでもうそれでいいや(時間ないので開き直れる)。毎回辺をvectorに入れて深さでソートしてから下へ行く。番号も全部上書きじゃダメでどこまで上書きすればいいんだみたいに思ってたけど単に上書きなしでよかった。その実装がよくわからなかったけど、適当に再帰する前後でインクリメントして、提出、運良くAC。

(解説を聞いて)毎回深さでソートしなくても直径さえ避ければいいのかあ。オイラーツアーで直径だけ節約するからこうなるのね。何も見えてなかった。