ABC230

遅めの5完。久しぶりに悪い順位を取ってしまった。(黄色だから当然だけど)Unratedで参加登録したからやる気が出なかった?Dまでは明らかに気持ちが入ってなくて、異常に遅かった。Eからは普段通りに戻った気がしてたけど、結果を見ると頭が変質してないかと不安になる(たまたまこうなることは普通にあるので、それならいいんだけど)。

A - AtCoder Quiz 3

問題文が長いけど、久しぶりにABCのAという感じのいい問題。問題文の内容もいい。n + (n >= 42) と書いて実行しサンプルが通らず、AGCを付けるのを忘れていたし、0埋めもしてなかったし、printf に切り替えて書式のdを入れるの忘れるし、入れる位置を間違えるしで、A問題だけで5回もビルドした。頭が回っていない。

B - Triple Metre

実際に文字列Tを構成しても間に合いそうだとは薄々気づいていたが、実装をイメージしてそこまで楽に書けないと思い正面から行く。最近の自分と違って「競技者」になっていなかった。Tは十分に長い。Sの置き場は実質3通りしかない。それぞれについて一致するか調べる。B問題も簡単だった。提出に警告が出ているのを見て気づいたが、文字列リテラルをconstでないポインタに入れていた。気づけば絶対に避ける書き方をしてしまった。

C - X drawing

入力が多いので問題文を短時間で理解することができない。また、問題文中のmaxとかがよくわからなかったが、A+kに関する不等式だと思ってみると要するにマス目からはみ出さないということであるようだ(全てちゃんと確認する気力はなかった)。クソ広い中から一部を出力せよという問題。実際は2本だが、ナナメの線1本で考えてみる。Aを基準にどんな位置にいるかわかればよさそう。さらに、実装して実行してを繰り返すうちにA, Bとの差の絶対値が等しいところを塗ればいいと気づいた。1始まりのままで処理できる。提出したコードはきれいだが、あまりちゃんとは考えていない。

D - Destroyer Takahashi

これも境界の処理に自信が持てずそのままやった。0-indexedにするには、Dからも1引いて点でパンチする感じになるのかな。コンテスト中は、幅1のパンチをする方針にしたので、R_iにD-1を足した。何でソートするかが問題だが、いつも通りRでソートすればよさそうなので、「何も考えずRでソートして左から処理」が常に通用しそうで少し嫌な気持ちになる。priority_queueを使うのかと思ったが、ちゃんと考えるとそういうやり方ではなさそう。まず、右端が最も左のものを一つとる。そいつは、右端をパンチするとして損しない。なぜなら、そのパンチが当たる壁はそれでいいし、当たらない壁は左端がそこより右にあるからパンチをより左にしても関係ない(コンテスト中はここまで文章化はしていなかった)。それによって、そのパンチした位置より左に(一部でも)ある壁はもう残っていない。あとは同じことを繰り返せばいい。当たらなかったやつを発見したらその右端にパンチ。当たらなかったやつの判定は左端との比較になる(サンプル合わなくて気づいた)。

E - Fraction Floor Sum

切り捨てなので積分みたいにやるのは難しそう。それで10^12だからきつい。でもグラフを描くとO(sqrt(N))が行けそうに見えてくる。まずsqrt(N)までは愚直、そこからは、(グラフで)高さがi(jにしたほうがよかったなあ)になるものが何個という考え方でいけそうだ。「自信はないけど一応ちゃんと考えた」みたいな状態で提出してWA。方針を変えてどの高さで分けるかを明示的に求めたが、またWA。Nが1や2だと高さi(1 <= i <= N)の区間の長さが0になることがないことを見落とした。

(追記)1つめのWAは、除算の結果がsqrt(N)未満のところだけ個数で処理したいところ、切り捨ての結果がsqrt(N)未満の最大の整数になる区間がはみ出しているからだろう。気づかなかった。そういえばサンプルの10^10が平方数であることに気づいてなかった。

「高さiが何個」ではなく「高さi以上が何個」でやって最後にダブってる長方形領域を引くというのもコンテスト中に考えていた。もう少し考えて、座標平面上に1*1のブロックを、右上隅の座標が(x, y)としてx, yが正整数かつx*yがN以下になる全ての場所に置き、ブロックの個数を数える問題にする。これは線対称だ。つまり原点を含みブロックに含まれる最大の正方形はブロックを同じ面積の2つの塊に分ける。正方形のサイズはfloor(sqrt(N))なので、その範囲で愚直に計算して2倍して正方形のぶんを引けばいい。いや、一応AC取ったけどここに書いたことに自信が持てないな。やはり調子が悪い。

F - Predilection

重複組合せっぽいけど、その方向で考えてみると負の数がある理由がなんとなくわかる。わからなかったので、逆転を狙ってGに専念した。

(追記)いや重複組合せではないか。仕切りを入れる方法が2^(N-1)通りあるやつ。全部正の数なら、これが全て区別されるので簡単。

(追記2)布団の中で解いたが、実装にもけっこう時間がかかった。累積和をN+1個並べた列からいくつかを選ぶ問題と言い換える。選んだ場所が違っても選んだものが列として同じなら同じとみなされる。ここで、ある列の選び方を考えると、左から貪欲に選べる一番左の数を選択してそれで後のものが選べなくなることはない(左を選んだぶん選択肢が広がっている)。よって、この選び方をすることで、選び方と操作後の数列が一対一対応する。あとはDP。左端と右端は必ず選ぶことに注意し、これまでの総和と最後に累積和の値sを選んだ直前の総和を保持して進める。両端がかなりややこしい。

G - GCD Permutation

順列であることを思い出せ。2つの世界があって、それぞれ素数の道があってどちらでも同じ道に属しているものの個数。解けそうで何やっても攻撃が通らなかった。