ABC156

久しぶりに楽しめたかな。欲を言えばFを通したかったけど。

A - Beginner

実装重いと思いながら時間をかけて書いた。改善するとすればmax(100 * (10 - n), 0)とするくらいか。これも制約や問題文をちゃんと確かめる必要があって大変だけど(さすがにn=10のとき100 * (10 - n)が0でない問題は酷いけどw)。

B - Digits

Kで割っていって何回目で0になるか。まあNは0より大きいので。

C - Rally

これBじゃないの。「整数値の座標」とのことなので全探索した。全探索しない方法もあとで考えたいところ。

(追記)時間計算量O(N)、空間計算量O(1)で解けた。まあこういう式になるのは知ってたけど、改めて計算した(こういう計算たまにしないとね)。

D - Bouquet

けっこう混乱してしまったが、要するに答えは2^nよりすこし少ないくらいだ。そこから、0本とa本とb本のケースを引き算すればいい(0,a,bは相異なる)。nがでかいので、都度計算するタイプのcombを貼る(計算量はn関係なくO(b)で済む)。

E - Roaming

Dと同じような感じだが。n-1回移動すればどんな配置も実現できる(最終的に人がいる部屋が少なくとも一つあるのでその部屋の人は動かなくていい)。1回のときは特殊だが、制約はk>=2だった。2回以上n-2回以下は、n>=3なので適当に迂回させればより少ない移動でできた配置は全て実現できる。0の個数がk個以下が実現できてそれ以外は無理なので、もうちょっと高速化できる気もするが、素直に0の個数がi個の通り数を足していこう。0の個数がi個のとき、n-i個に分けるのでn-i-1個の仕切りを入れる。各部屋に1人以上なのでn人からn-i人減らしてn-i-1個の仕切りを加えてn-1個からn-i-1個を選ぶ。0の入れ方はn部屋からi個選ぶ。掛けて足していく。

F - Modularness

なかなか読むのが大変だけど。aは単調増加っぽいけど停滞することもありm以上になったら戻されたりもして、それでn-1回中何回増えるかと。とりあえずO(kq)の時間は使えるので、a_0からa_kまでk+1個のシミュレーションを書いた。これをどう使うか。a_k-a_0 mod mだけずれていくんだよね。0以上m未満の範囲で棒グラフみたくしてそこから棒の長さをmにして幅mの箱をずらして、とか考えても無理そう。で、k個のペアそれぞれについてa[i]<a[i+1]となるようなオフセットの範囲は求まるなと思った。n/k回のループで毎回のずれをstd::setとかに記録して二分探索で(log付いちゃうけど)個数はわかるかなーとか。しかし、kが小さいかもしれないことを忘れていた。n/kが5000以下とは限らない。

次に思いついたのは、そもそもa[n-1]は求めることができる。基本的には増えていくけど、m以上になったらmを引かれてしまう。増えるはずが減ったということが、a[n-1]/m回くらい起きているはず。という方針をバグと戦いながら頑張っていたが、dがmより大きいことがある(特に、ずっと大きいこともあるのが痛い)ことを忘れていた。当然サンプルは通らず終了。終了後、n--; x %= m;と最初にするようにした。間違った方針に時間を費やしていては、1時間はあっという間だった。ん、dを最初からmod mとっておけばどうだ?(ほんと色々アイデアは出てくる)

(追記)dをmod mにすることで解けた。想定解と同じだ。