ABC206

5完。今日は朝から調子悪かったけどまあコンテストは普通にできた。

A - Maxi-Buying

"Yay!"はもうしないって言わなかった?非本質で悩んで2分以上かかったのクソ。本質は切り捨てで、108を掛けてから100で割る(整数演算だとここで切り捨てになる)。

B - Savings

答えはO(sqrt(N))になるので、愚直にシミュレーション。

C - Swappable

条件がA_i=A_jならよくあるやつ。だから簡単なんだけど、簡単なのに自分が実装で悩んでいるから本当に簡単なのかと不安になる。最初引き算で書いてなぜかサンプルが合わず混乱したので、直接違うやつの個数(すでに見た個数から、すでに見た中で自分と同じやつの個数を引く)を足していった。

(追記)サンプルが合わなかった原因は、mapがまっさらなままだったから(は?)。ちゃんとmp[a[i]]++してから提出してWA。原因はオーバーフロー。

D - KAIBUNsyo

全部同じ数にすれば回文にはなる。どこまで回数を減らせるか。数列に含まれる数の集合を考えて、それをいくつかに分けてグループ内を同一視することで回文にするという問題だ。ということでUnionFind。回文で対応する位置同士は同じグループに入る必要があり、操作の順番によらず操作回数は変わらないので結合された回数を数えればいい(元々同じグループだったら数えない)。ややてきとうに投げた。

E - Divide Both

最大公約数で割って1でないという条件を考える。x < y と仮定すると、yがxの倍数でないことと同値。x = y のとき条件を満たさないので、x < y のときの個数を求めてその2倍を出力すればいい。区間内の倍数の個数は割り算で簡単に求まるので、互いに素でないペアの個数が本質。ここがかなり難しかったが、イメージに反してゴリゴリに包除原理でやって間に合うことがわかったのでそうした。包除パートの時間計算量は素因数の種類数をKとしてO(K*log(K))だが、実験すると10^6まで全部やっても10^8にもならない(Kは小さいことが多い)。こういうとき線形篩を持っていると1からNまでO(N*log(N))で素因数分解できるので良い。あとは普通に包除して互いに素でない個数を求めて足し、1以外の数に対してはその倍数の個数を求め引く。他の正整数と異なり1の倍数は1と互いに素なので、1は特別扱いする必要がある(ここややこしい)。最後に2倍して出力。

F - Interval Game 2

区間じゃなかったら解けないってこと?全然わからん。区間DPみたいにならんかと思ったけど、2つの区間に分かれたときにどうなるのかわからない。

今回はDまでの早解きに成功したのでEFにたっぷり時間を使えてよかった。