AGC021

A - Digit Sum 2

短い問題文。つよそう。とりあえずN自体の各桁の和を求めるコードを書く。それを使うかどうかはわからないが、書いて損はないと思った。すると、全部9にすればよさそうだと気づいた。考えてみると、最上位を1減らすだけでそこ以外を全部9にできるからこれが答えだ。9999は8999にしちゃダメなので、両方求めて大きいほうにする。最上位が1でもいいし、1桁の数でも両方見るなら問題ない。手間取ったかと思ったが、順位表を見るとかなりいいタイムだった。

B - Holes

最初はボロノイ図を描かせるのかと思ったが、垂直二等分線の角度を見るだけでいいのはすぐにわかった。内側にある点は0を出力すればよい。凸包(変換できなくてキレた)がわかればいい。atan2の使い方もググった。難しそう。Nが100なので、O(N^4)で各点が各三角形に含まれるか調べることも考えたが、これもパッと書けない。yukicoderで「点と三角柱の内外判定」にfavを付けておいてその程度かよと思った。
アレだけどWikipediaの「ギフト包装法」を見て実装した。直線上に点がたくさん並んでいる場合、近いのを選ぼうとしていたが、atan2を使っていたのでその方法がわからなかった(ちょっと足すとかだと精度が俺では見積もれない)。外積って書いてあったので「ああそういうことか」と思いながら外積を使った(doubleのままでもこの程度なら整数を厳密に扱えると信じた(信じるな計算しろ))。
外積は、同じ向きのとき0になる。180度違っていてもそうだというイメージを持っていなかった。ぐるぐる周って戻ってくる角度の話は難しい。これが170度以下だとわかっていれば簡単に処理できるが、180度のケースもあるので頭がぐるぐるになる。
番号を間接的に扱っているので大変だったがなんとか最後まで書けた(大量の時間を消費した)。しかしサンプル2の順番が合わない。謎だったが、最初にソートして順番の情報が消えていた(はー)。ソートせずにmin_elementで位置を取得。i00というクソダサ変数名を使った。垂直二等分線の代わりに辺の角度を使っていたが、その角度2つの差がどの点の取り分を表すかもひとつずれていた(というか何も考えてなかった)。一応サンプルが合ったので提出。WA。
手元で直線上に何個か並べただけのサンプルを作り、間違ってそうなのでそれでデバッグ。距離を求めるところがdx * dx + dy + dy;になっていて酷かった。直線上に複数あるとき近いのを選ぼうとしていたが、遠いほうでいいと気づいた。端っこの点を選べば他の点の分布はある180度の範囲に収まるというのもはっきり認識したのはこのへんだったかも(今まで何を書いていたんですか)。
2回目の提出でACとなった。1時間以上かかっているのは内容が内容だけに仕方ない。自分にとってこれは競プロで速度を競う領域のことではない。勉強不足とは言えるか。まあそれも仕方ない。偶然かもしれないがACまで持って行けたのはけっこうな実装力だと思う。時間がかかったから実装力がないとも思ったわけで、実装力とは何かがまたわからなくなった。

C - Tiling

時間がなくてACを狙う緊張感は味わえなかったが、考察はしていた。見た目は場合分けがクソめんどくさそうな問題だが、AGCで出題されていることから何かきれな方法があるに違いないと思い、できるだけ場合分けしない方法を探った。
コンテスト中に考えていたのは、2*2の正方形で盤面を覆っていくというもの。幅が奇数なら右端を縦長のタイルで埋める。高さが奇数なら下端を横長のタイルで埋める。右下を空き升にする。正方形を作るときに縦長横長どちらを優先的に使うかを両方試す。
ただ、タイルが1枚だけ余って正方形が作れないときに不安はあった。コンテスト後に、「空き升を左下にしたら?」と考えて、四畳半というミニマムな例を見つけた。
(とりあえず終わり)
(続き)AC。四畳半に気づいたうえで手早く実装できるか、という感じ(それはそうと、「四畳半」で通じるの面白い)。証明はしてないけどまあ自由度高いしこのくらいは論理的な余裕があるだろうという。
まず、'.'で埋めた盤面を用意する。幅が奇数なら左端に縦長を置けるだけ置く。高さが奇数なら上端に横長を(幅が奇数なら左上は空けて)置けるだけ置く。右下に残った偶数*偶数の長方形領域は、タイルを2つペアにした2*2の正方形で埋めていく。両方のタイルが1枚以下になったら贅沢に1枚だけ置く。
さて、幅も高さも奇数のときは左下隅が必ず空き升になっている(そのように構成した)。そこへ横長を突っ込み、その横へ縦長を置くことで、縦横1枚ずつのタイルを一番左下の2*2正方形へ四畳半的に効率よく置ける。正方形を埋めていくときは、この正方形が最後となるようにする(唯一選択肢の多い正方形であるため)。
最後に、タイルが余っていれば"NO"、残りがゼロなら"YES"で配置も構成済み。
目的が、全てのタイルを置くことか、すべての升を埋めることか、わりと混同した。もちろん「全てのタイルを置くこと」なんだけど、コーディング中は抽象的な思考になり混ざる。