競技プログラミング

訓練

青 diff の AC 数が 50 を超えた。自力で解ける気配は無い。

マスター・オブ・場合の数 の §1 を解いた。意外と DP の観点が役立つ。

ABC 335

ABC 335 に参加した。 4 完だった。

感想

今回も手続き型言語 Haskell でゴリ押ししてしまった。

茶 diff の C, D が難しかった。来週は緑色コーダーに戻るかもしれない。

解法

A 問題 では (`snoc` '4') とか (<> "4") が書けたら格好良かった。

B 問題nubSort $ 全探索 の形で解いた。タイピングが苦手なので、空白区切りの putStrLn をスニペットに入れようと思った。

C 問題 ではスネークゲームを連想して混乱した。先頭の残像の位置が問われると思えば、可変配列をリングバッファとして使ったり、 cojna/iotaData.BufferpushBack していけば良かった。

より上手な解答として可変配列を使わない提出が見れた。 scanl で位置の一覧を作ってから、改めてクエリに答えていくみたい。頭を使う必要があって難度は上がると思う。

D 問題 では螺旋状に答えを作っていけば良いことが分かった。内周がこれ:

 --|
 |T|
 |--

1 つ外側の周がこれ:

----|
|   |
| T |
|   |
|----

それぞれの周を描くためには、左上の頂点からスタートし、長さ \(2 i\) の辺を 4 回描いた。 accumArray などは使わず、可変配列へ都度答えを書き込んだ。

別解としては、外周から始めて内周へと近づいていけば、壁 or 探索済みのセルにぶつかる度に 90 度回転するだけで済むため、簡単になりそう。

E 問題 は苦手なグラフ問題に見えて飛ばした。最長距離を求める不思議な問題だった。

コンテスト後に Dijkstra や 01-BFS っぽいのを投げてみたものの TLE 。もともと最短経路を求めるアルゴリズムだし、やっぱり上手く行かないみたい。同じ数が振られた隣接頂点を 1 つに潰すと DAG になり、 DP で解けるそう。後でやってみる。

F 問題 が解けなかった。右端から計算する方針は立てたものの、高速化ができなかった。 evima さんの解法 に従って \(dp[x][i \bmod x]\) を周期和とすることで upsolve できた。力こそパワー……

読書: PBT 本

実践プロパティベーステスト を 28% まで読んだ。ジェネレータが生成したテストケースを分類し、何 % のテストがどの分類にあたるかを確認できることを知った。

実際、ランダムなテストケースを作るだけでは、境界値を見れず素通りする確率が高い。 AtCoder における QuickCheck の使い方としては、実質的に総当たりをしていた。自分でループを書いても良いが、失敗したケースの表示まで QuickCheck がやってくれる点が便利だった。

PBT 自体の良さはまだ感じ取れていない。 matklad 氏が invariant 大好きマンなので 、彼の視点を理解するためにも読み進めてみたい。