|XB-AY| = 2 の式までは出ていた。しかし探索ができる制約ではなく、そこから何も手が出なかった。高校数学の演習課題でよくあったパターン。手段は授業で教わっているので、ヒントをもらえば最後まで書ける。だけど最初のとっかかりが何もなくて途方に暮れる。それはつまり、知識はあれども理解するには至っていないということなんだろう。そういうようなことが『技術の創造と設計』(畑村 洋太郎) などに書いてある。x に隣接するいくつかの頂点からなる(空でも良い)集合 S であって、∑y∈SWy<Wx であるものを選び、S に含まれる頂点それぞれに 1 個ずつコマを置く」のシグマを見落としていて、Wy<Wx なるすべての y∈S にコマを配置できるものだと思っていた。残り 10 分でこの思い違いは厳しいが、幸いにもある頂点を選ぶ選ばないの愚直2乗 DP が許されていたので間に合った。うれしい。何番目まででいくつ選んだときの最大がいくつという DP が求められていたら無理だった。解法は、W が小さい頂点から順番に答えを計上する。それは配置されているコマ数×倍率。倍率を決めるために W が小さい頂点から順番に DP をしているし、ある頂点の倍率を決めるためにも W 未満の範囲でまた DP をしている。■自分のすべての提出。C 問題が解けていないことを除けば上出来。コンテスト成績証。1400 に復帰しました。1500 にもう一度のせて青を窺いたいところ。■C 問題。提出 #50395575 (C++ / AC / 637 Byte / 93 ms)。提出 #50396690 (Ruby / AC / 259 Byte / 66 ms)。Ruby が速すぎる! コンテスト中にこれが通せないのはお前が抜けてるからだってはっきりわかんだね。■C 問題。Ruby で最初の AC であるこちらの提出 #50356929 を見ると、18 行目の
uniq! がポイントかなと思った。自分の TLE 提出である #50356164 が3行目でやってる文字列置換も目的は同じだけど、やり方が拙くて不十分。自分は経路の冗長性を取り除こうとしているが、経路をたどった結果の到着点の重複を取り除くことで冗長性を除くべきだった。だけどそのときは方法が思いつかなかったんだよ。理由もわかる。重複を取り除くためにはいったん配列などに溜めて並べて比較する必要がある。だけど自分の解答の構成はループを回して逐次的に移動先を更新していた。同時には1つの到着点しか存在していないのだから、それらを比較して重複を取り除くという発想が自然には出てこない。全体を俯瞰して最適な構成を考えることができなかったのは、問題の理解が浅かったからにほかならない。残念だね。require 'faster_prime' しているものを見つけた。なにそれ知らない。■E 問題「Last Train」。これは精進。パラメータが多くて頭が壊れてしまった。解法はすんなり出てくる。ゴールの N に到着する最も遅い電車を始点にしてプライオリティキューでダイクストラ法をする。しかしパラメータが多いのと、最短ではなく最遅を求めるというので、普段と勝手が違って無限にバグを生み出し続けて時間切れになってしまった。キューに入れるのは時刻と街のペア。たくさんあるパラメータはキューに入れる次の時刻を計算するために使う。あとはがんばって頭の中を整理すれば答えは合う。だけど昨日は、列車の運行を逆向きにたどっていることが合わさって、出発時刻と到着時刻の前後関係がどうあるべきなのかとか、判断をするその時刻に k 項ある等差数列の先頭末尾どちらの数字を使うのかとか、およそすべてのポイントで間違えた。■F 問題「Black Jack」。これも精進。昨日も今日も WA を出したがやっと AC が出た。まず、ディーラーの値 y が L≦y の範囲でどういう確率で分布しているかを知るために 0 から N まで DP をする。E 問題もそうだったけど、この問題も考えることが多くてこんがらかる。y<L の範囲ではサイコロを振るけど、L≦y の範囲では振らない。今 DP で求めようとしているある場所にいる確率というのは、同時に、サイコロを振って次の場所にいる確率を求めるために使う値にもなるのだけど、L を境界として両者が異なる値を取るということ。そこをきっちり区別しなければいけない。ところで、サイコロは D 面あり、DP のためには D 個の値の合計が知りたくなるが、愚直に合計するには D の数が大きすぎることがある。こういうことを1つのループの中で全部考えながら整理するのは非常につらい。今回も evall のとき(20240128)と同じように class を使った別解(#50640033)を書いた。解答の後半は前半とは逆に N から 0 に戻る逆順の DP をした。N にいるときがスタート。サイコロを振れば必ず負け、サイコロを振らないときは y=N の場合を除いて勝つ。y=N の場合の確率は前半の DP ですでに求めている。後半の DP でもサイコロを振った場合の勝率を求めるために D 個の値の合計が必要になるので、前半と同じ class を使って楽ができる。そのクラス(LastNSum)を読み直していたら、@first が完全に無意味なことに気がついてしまった。pop 操作があるなら意味があっただろうけど、ないのでいらない。■自分のすべての提出。レート遷移は知らない。どれだけ減ったかなんて知りたくない。