ABC235

6完。最近はコンテスト外で競プロやってないけど、プログラミングはしてて、いい感じの生活。1週間ぶりのコンテストで(直前も全然関係ないことしてて)、やや「慣れ」のなさは感じたが、体の動きは鈍ってなかった。

A - Rotate

これをループなしでどう解けと。数値として受け取り、10で割ったあまりを100倍して上に乗せる(元の数は足す前に100で割る)のを3回繰り返した。1分は超えたものの、体感でけっこう素早くやれた。今思うと、文字列で受け取ってstd::rotateしてstd::stoiだったなあ(stoiがパッと出てこない)。

(解説を読んで)うわあ(時間ないとはいえ)桁和の111倍に気づかないのゴミか?

B - Climbing Takahashi

サンプル3にもあるが、高さが同じときは移動しないことに注意。これは簡単。入力も、高橋君が止まったところまでしか受け取らない実装にした。

C - The Kth Time Query

数xが現れたときインデックスをunordered_map<int, vector<int>>に入れていけば、k回目に現れたものはvectorのk番目に入っている。存在するかの判定は、vectorのsizeとkを比較。まあ座圧もできそうだけど、C問題でけっこう知識要求してくるなと思った(これが知識に分類されるかは知らんけど)。

D - Multiply and Rotate

10^6なのでグラフでできる。rotateはA問題と同じように(桁数が一定ではないので対象となる数以下で最大の10冪を求める処理が入る)。で、最初はN以下の数を考えていたが、Nを超えてから戻ってくるルートもあると気づき、幸い10^6「未満」という制約なので(桁数が減る操作は存在しない)常に999999までの頂点を持つようにした。いやあ危なかったと思って提出したらRE。10^6の2乗はintに収まらない。これはけっこう面白いペナだった(あまり見ない場所でのオーバーフロー)。

E - MST + 1

「一意に定まる」を見て「いやそんなわけないでしょ」みたいなことを口に出した気がする。でもクラスカル法の手順を思い浮かべると確かに全てのステップで一意なんだよね。クラスカル法わかってないので仕方ないです(完全に道具として使ってる)。さて、その一意に定まる手順の中で追加された辺の番が回ってきたときにどうなっているか。これはクエリ先読み。今思うと元の辺とクエリをまとめてソートしてもよかった。コンテスト中に実装したのは、別々にソートしてしゃくとりみたいにして、今の段階で選ばれるクエリの辺をまとめて処理するもの(番兵として辺を1個増やす)。典型かつ天才みがあってABCの問題として良い。

サンプルが合って提出したがサンプル以外全部WA。ソートしたらインデックスわかんなくなるじゃん。クエリ先読みの基本を忘れている。今回はコンテスト体験を重視できていたのでペナを出してもそんなに嫌な気持ちにならなかったが、それでも自分のミスで他の問題を考える時間が減るのはやはり嫌だった。

単純グラフと書いてあると思い込んでいたが、自分が見た文字列は「無向連結グラフ」だった(AtCoderで「単純」と書いてないことがなさすぎて「ああいつものね」で終わらせてしまう)。辺を追加したときに多重辺となりうることは気づいていたけど。

F - Variety of Digits

桁DPっぽいので少し前に書いたブログを読む。10進法の場合のコードも載せてるのほんとえらいし、DPの添え字の意味も2進法の側にちゃんと書いてあってほんと助かる(桁DPマジで難しいので身に付かない)。しかしその上でも難しい。まず、和ではなく個数を求めてみる。「全て含む」というのが厄介で、「一つでも含む」なら条件を達成したかどうかのフラグだけでいい(「一つも含まない」でも同様)。なるほど10^4と制約がやけに小さいのは、2^10通りの状態を持つからか。これ(コピペしたコード)は配るDPなので、10通り試して行き先を愚直に求めて足していけばいい。先頭が0であってはいけないので、けっこう混乱してかなりの時間がかかった。個数が求まったら、次は和。この問題、解ける確信がないまま書き進めるしかない。どうやら個数も必要そう?和は普通に配るだけでよくて、桁を追加したぶんの寄与を個数を掛けて求める必要がある。自分の実装だと、DPテーブルのメモリ節約をしていないし、追加する桁を10通り全部試しているので、定数倍がかなり心配になる。まあ通るやろ(1204ms)。

G - Gardens

Fで詰まったときにちょっと覗いたが、無限人解きそうな数え上げに見えて確かに難しい。そこで順位表を見てすぐFに戻った。Fを通して戻ってきたが、「すべての庭に少なくとも 1 株以上の苗を植える。」の条件がなくても、二項係数のO(1)では求まりそうにない和が必要になる。しばらくして、使う和が連続した位置にあるので差分計算できる可能性に気づいた。パスカルの三角形で考えていて、一つの和をO(N)で求めたらO(1)で更新していける。あとは包除パートだと思ったら、できない。残り時間も少なかったけど、これは時間があっても無理だった。「苗を植えてない庭がK個以上」の場合の数を求めることができない。他のアプローチも思いつかない。

(追記)庭iに何も植えないと決めたときの植え方たちという集合がN個ある状況を考えると、まんま包除原理。包除パートは完全にいつものなんで、これが見えないのは単に包除原理そのものの難しさだ。