Mujin Programming Challenge 2018

ゴミ。

A - コンテスト名

今気づいたが、日本語オンリー回だからタイトルが珍しく日本語だ。なんか一発でできる関数ありそうだなとか思いながらsubstrと書いてみて、短かったら短い文字列が返ってくるしこれで比較すればよさそうだなと思い、そのまま書いた。

B - セキュリティ

まあやるだけ。普通に書くと比較回数が|S|ではなく|S|+1となり、何かきれいに書く方法ないかなあと思いながら提出。まあさすがに無理か。

C - 右折

重い。これは難しいCじゃなくて普通のDだ。と思ったがわかってしまえば簡単で、各点について上と右に何マス進めるかわかればその積があれだ。その点でそう曲がるやつの個数。何マス進めるかは端から見ていけばいいので計算量も大丈夫。ただ、実装が大変そうだ。回転させようか迷ったが、各方向から見ていく4通りのコードを書いた。自分自身を1つめのマスとすることで、まあ1多いんだけど引くのは簡単だし、壁を0にできて自然かと。計算量がそこそこでかいのはわかっていたが、現実に107msもかかってびっくりした。AtCoderでは、なんだかんだ50msとかで済むイメージしかなかった。

D - うほょじご

問題名を見てなかったが、互除法って書いてあったんだね。さて、範囲が狭い(高々100万)ので、これは簡単。しかし実装が重い。普段のAtCoderをやっていると忘れてしまうが、自分は実装力がそんなにないのだ。できそうだと思ったことを具現化する力、深い理解かワープスピードが必要になる。まあ書く。サンプル1で値が13から18に大きくなっているのを見てドキッとするが、値が0以上1000未満の範囲から出ることはないのでこの方針で大丈夫。1つずつやっていけばいいと思っていたが、ループするかどうかがわかったときにもう1回潜らないといけないのが面倒だ。少し考えてメモ化再帰にした。慣れないので時間はかかるが難しくはない。操作の途中でメモ配列を参照しそうになるが、配列には操作が完了したタイミングの情報を入れているのでそれは危険だった、思いとどまる。反転する操作も念のために予め計算したものを使うことにした。あとは数えるだけ。

E - 迷路

BFSで行けると思ったが、その場に留まることができるのでキューの中身が増えてO(マスの数)を超えてしまいそうだ。ただ、右に行かず留まった人がそれよりあとのタイミングで右に行くのは無駄なので、実際はキューの中身がこんもりした塊になる必要はなく表面だけでいいはずで、何か方法はありそうだ。ちょっと大がかりだが、キューを4つに分ければいいのではないか。新しいノードに到達したとき、その直後の移動方向は4通り考えられるので、例えば右に行くなら右に行くキューをpopする。ちょっと複雑ですっきりした見通しはないが、まあ計算量的には行けそう。サンプルが無限ループする。行ける全てのマスに到達したら抜けて-1。サンプルが合わない。文字列dの同じ文字を連続して使ってはいけないので、最短時間が同じノードがキューに入ってたらそこまでとする。提出するも1つだけTLE。
よくわからんけどループを抜けるのミスってるかもしれないから1.2秒経ったら-1を返すようにしよう。WA。はー、TLEしたやつの答えは-1じゃないのか。意外だったが、言われてみればそうするだろうなという感じ。なるほど、Kがけっこうでかいのを忘れていた。問題が難しいと、本質的な困難と目している相手以外の難しさがマスクされてしまう。しかしこれは修正が容易でない。時間もないので方針に迷う。いやほんとこのタイミングで来るのは困るのよ。Fを考えられないのも残念だが、Eの考察をこんな残り時間の少ない環境でしなければならないことも残念だ。更新が起こる次の文字位置がO(1)わかればいいのだから、更新が起こらなかった方向の組み合わせ16通りについて次の文字位置を表す配列を用意すればいいのでは?でも残り5分。もう何もできず変な空間を漂っていたあの時間が本当につらかった。ていうか今がつらい。