ABC277

5完。このセットで青パフォなら上出来。上出来ならいいという話ではないんだよな。楽しめましたか?

A - ^{-1}

1-indexedで実装した。見つけたら答えの変数にインデックスを入れる。これはB問題でしょ。

B - Playing Cards Validation

トランプっぽい。52枚のうちの一部を取り出したものになっているか判定してくれと。1文字目と2文字目の条件で被ってる文字がなさそうなので、長さ128の配列を用意して文字を入れると何文字目用の文字か出るようにした。数字はそれをfor文でセットしたが、提出前に確認したら0以上9未満になってて間違い方がやばかった(正しくは2以上9以下)。被りのチェックはstd::setで。insertされなかったらダメ。

解説のように"HDCS"とかを用意してやりたかったが、問題文からコピペするとカンマやスペースを除く手間があるし、いや自分の方法のがよっぽど手間なんだけど、そこから一致する文字があるか判定する処理もすぐには見えなかったので。力不足かあ。B問題で。面白くない。

C - Ladder Takahashi

グラフかと思って書き始めたらそういえば10^9じゃん。そもそもUnionFindでいい。unordered_mapで階に番号を割り振っていく。サンプル合わず、1階に番号を割り振っていなかった(自分の実装だと自動的に0番となっていた)。

D - Takahashi's Solitaire

同じ数でもいいんかい。一番大きな塊を取るだけ。しかしループしていることもあり実装が相当重い。

E - Crystal Switches

一瞬好きに移動できそうに思うけどスイッチがない頂点にいるとそうでもなかった。スイッチの状態を加味すると、グラフが2個あってスイッチで行き来する感じになる。01BFSをする。最初BFSでやってたらサンプル合わなかった。スイッチ押す回数は含まないって最初はわかってたのに忘れるんだよな。

F - Sorting a Matrix

各行の(0以外の)最小値と最大値を求めてpairに入れてソート。これで順番になっているのがまず必要。なんかこれで提出しようとしてしまったけどいくらなんでも簡単すぎると思って見直すと列毎にしか入れ替えられないの忘れてた(??)。列をソートしようとするが、これは順序になっていない。答えがYesならソートできるというものでもない。有向グラフを作ってDAGになっているか判定すればと思ったが、列同士の関係の個数はO(W^2)。もう少し考えて、いくつかのインデックスの列を矛盾がないように合成できるかという話に。ここらで一旦Gに行った。ここまで難しいと最初からわかっていればもっと早くGを見たが。

改めて考えると列にしてしまえば隣同士に有向辺を張るだけだから、辺の数はO(W*H)となりOK。同じ数が複数ある場合が厄介だが、違う数へ辺を張るとき1個頂点を追加してそこを経由するようにすれば頂点数も辺数も2倍くらいで済む(2乗とかにはならない)。あとはグラフ構築してatcoder::scc_graphで全体がDAGになっているか判定すればいい。コンテスト終了後、15分遅れでAC。「正の整数」が太字の理由が最後までわからなかった。

G - Random Walk to Millionaire

かなり難しい。とはいえ何かでまとめてDPするしかないだろう。頂点と移動回数でDPか?レベルか?計算量が3000の3乗になりそうだけど。もらえるお金が2乗なのは+1,+3,+5みたいに分解できそう。思ったより難しいのでFに戻る。

終了後落ち着いて考えると、頂点毎に情報を持ってK回更新するDPじゃん。これならO(N*K)で済む。レベルの期待値を求めるだけなら簡単だとようやく気づいた。ということで、確率とレベルの期待値をまず持つ。あとレベルの2乗の期待値と獲得金額の期待値?何もわからないけどめちゃくちゃ願望で書くと、レベルの2乗の期待値はレベルが1増えるとき(1+レベルの期待値*2)だけ増えるってことに。サンプルが合ったので提出するとACに。グラフ構築してたけど、単に有向辺をM*2個持って順に処理するだけだった(そのほうがだいぶ速い)。解説はわからんし自分の解法の正当性もわからない。無能。

Ex - Constrained Sums

(追記)解説の言い換えを見て自分で図を描いてみるといや確かに。これはやべえ。実装に入るが、初めての実装(atcoder::two_sat自体は使ったことあるがそういう次元じゃない)なのでハチャメチャに時間がかかった。X_1が-1以下であるというのはFalseでM以下であるというのはTrueなので2-SATの変数には含めなくていい(そこが関係するケースではFalseならFalseとして同値になるように条件を変えることでカバーできる(同じ変数を2つ並べる、常にTrueだから消す(これで無限個の整数から必要な区間だけ残る)))。「0以下でない」と「1以上」は同値なのでまとめる。「0以下」かつ「1以下でない」となったらダメなので、これの否定を加える。RがMより小さいときはR以下でなければならないというのを加える。RとL両方書くのが大変だが、けっこうきれいな見た目になる。割当を一つ得たら、その条件を全て満たすX_iは一意に定まるのでそれを出力する。いやあ、解説見たときはこの言い換えさえ教えてもらえば簡単なのかなと思ったけど、「自分にとっては」とんでもんなく重くてやはりExだなあと。