ABC271

6完。直前までプロセカの配信見てたしなんなら始まっても聴いてた。それ込みでも別に調子は悪くないという感じ。ここ数日精神状態が悪いけど、ABCを楽しむという意味ではばっちりだった。

A - 484558

1桁ずつ出力。1桁の出力は関数にした。10未満かで場合分け。2分ちょっとかかったけど、内容的には上々。

B - Maintain Multiple Sequences

久しぶりにやるだけなBだ。教育的でいいと思う。

C - Manga

かなり時間がかかる。これまでの痛い経験から飛ばすことも当然考慮に入れるが、ちゃんと内容がある感じなので頑張った。結局20分以上かかっている。

まず、答えはN以下だ。つまり、N+1巻を読むことはない。そこから先の巻は全部売ってしまっていい。ダブってるのも全部売る。長さNのvectorを用意して、売った後に何冊(0か1)持っているかという形で情報を持つ。これで売るものは全部だと勘違いして1WA(たまにあるとんでもない勘違い)。実装していると、売っていいかどうかの判断がかなり厄介そうだと気づく。結局、前と後ろから同時に攻めていかないといけない。ない巻があれば売ったものから補充して、それが切れたら後ろから売っていく。ちょっとこの組み立ては300点の難易度を超えている。

D - Flip and Adjust

まあDP。ちょっとイメージができないので、とりあえず判定だけするDPを書いて、たぶん復元できるでしょと。書きあがったら、さすがに理解が深まって復元できた。Sから始めて後ろから。戻れる場所があればどっちでもいいから戻る(Sの値も引き算する)。どちらの向きを選ぶかは、長さ2のループで処理できるので楽。

std::arrayが、コンパイルは通るけど赤波線引かれてしまい、コンテスト中はグローバル変数の2次元配列でやった(IDEはVisual C++で、コンパイルMinGW)。最近環境リセットしてbits/stdc++.hが整備できてなかった。Visual C++の__cplusplusが原因っぽい。

E - Subsequence Path

「良い経路」でなくていいならダイクストラ法だが。ちょっと捉えどころがないので一旦飛ばす。Fを通してGを少し考えてわからないので戻ってきた(体感難易度でGがEを超えたタイミングでEに来る)。

数列Eの最短経路問題として捉えたらどうだろう。辺を頂点にするのがややこしいけど。これはDAGなのでDPできるが、計算量が2乗になるかもしれない。困るケースを考えようとしていると、遷移元となる辺の行き先の頂点に最小コストを持っておけばいいという説を思いついた。なんか都合よすぎる気がするのでかなり警戒していたが、実装していると正しそう。数列EでDPすると思ってたけど、実際は元のグラフの頂点でDPしていた。一応これでAC。数列Eに行って戻ってきてしまった感じ。ちゃんとわかった気はしない。なるほど解説のように考えればすっきりしているか。これ水diffはけっこうびっくりする。見たことのない考え方を要求されて難しい。

F - XOR on Grid Path

愚直が行けなくもないような制約。少しだけ高速化できればいいと思って考えていると、N-1回の移動で到達する場所はナナメの直線上に並んで逆側からも同様だと気づいた。まさにmeet-in-the-middleという感じで気持ちがいい。こういう良さを求めてるんだよな何に対しても。制約の意味もわかった。で、ここからは少し難しい。何でまとめるか。移動後の位置がN通り、移動後の総xorが2^N通りでしかも0以上2^30未満と範囲が大きい。結局、位置毎にunordered_mapを持った。定数倍は多少悪いかもしれないが、O(N*2^N)に収まっている。出会う場所のxorを2回とらないように注意。相手の通り数を足していって答え。

G - Access Counter

終わってみればただの行列累乗だが、何時間後に何回目である/何回目になる確率というぼんやり広がるイメージから具体的に見る方向を定めて捉えるというのはなかなか抽象的な思考が要求されて高難度だと思った。

1回目のアクセスが何時になるかを考える。0回目のアクセスが23時にあったとしてよい。そこから、0時から23時まで24回計算して、それでもまだ1回もアクセスされていない確率が残る。これの分配は結局1周目と同じ割合になるので、合計が1になるよう全体に同じ数を掛ければいい。1回目は、最後のアクセスが23時として考えればよかったが、2回目以降も24通りのスタート地点を考えれば同様にできる。とはいえ、添え字を合わせるのが相当しんどい。スタート地点をjに固定し、jの次の場所から配っていく。行列には、スタートする縦位置を1ずつずらしながら縦書きしていく感じ。

(追記)解説放送聞いてて「おいおいおいおい」ってなった。0で割ってる可能性。もちろんコンテスト中も忘れていたわけではないが「これはOK」みたいな感じで流してた気がする。もはや思い出せない。1周してアクセスされない確率がmod 998244353で1のとき困る。そうならないことは、Aの個数(順番関係ない)とXとYを全探索して確認できるらしい。なるほど。制約が違っていて実際1になったらどうなるのかというのが難しい。答えは有理数になるが分数で表したとき分母が998244353の倍数になるからmod 998244353で表せないということかな。まあ計算過程で現れたからって答えもそうなると言えるわけではないが。その辺もクリアできるなら制約から1になることはないって言える。思ったよりきわどい問題だった。ACしたときの自分が間抜け面に見える。