ganmo::cout

競技プログラミング始めました

Codeforces Round #554 (Div. 2)

なんとか青維持しました(1632→1677)
またしてもDが解けなかった(くやしい)

A - Neko Finds Grapes (500点)

問題: Problem - A - Codeforces
鍵と錠の偶奇だけが問題になるので、それぞれ偶数と奇数がいくつあるか数えてmin{偶鍵, 奇錠} + min{奇鍵, 偶錠}を出力してAC。O(n+m)

拙解 (C++14): Submission #53228308 - Codeforces

B - Neko Performs Cat Furrier Transform (1000点)

問題: Problem - B - Codeforces
最上位ビットから見ていって0があれば反転して1を足し…というのを愚直に繰り返す。0が最下位ビットまで連続するケースに気を付けて、立っているビットの数が最上位ビットのindex(1-indexed)に一致すればそこで1を足さないで奇数回の操作でおしまい。この操作回数と反転するときのビットのindexを出力する。こうすれば操作回数tは高々2(1+\lfloor \log_2 x\rfloor)回になり、x \le {10}^6 < 2^{20}からt \le 40を満たしてAC。O(\log x)

拙解 (C++14): Submission #53237080 - Codeforces

C - Neko does Maths (1500点)

問題: Problem - C - Codeforces
{\rm lcm} \{a+k, b+k\}を最小化する問題。まずは{\rm lcm}\{a+k, b+k\}=\frac{(a+k)(b+k)}{{\rm gcd}\{a+k,b+k\}}から、kをなるべく小さくしつつgcdを大きくしていくと良さそうなことが分かる。a\le bとして一般性を失わず、またこのgcdをgとおくと、a+kb+kはいずれもgで割り切れてa+k \equiv b+k \pmod{g}なので、kを相殺してaを移項し、b-a\equiv 0 \pmod{g}とわかる。したがって、b-aの約数がgの候補となる。こうして列挙したそれぞれのgに対して、k=g-a\%g=g-b\%gが定まって、問題文にあるように\DeclareMathOperator*{\argmin}{arg\,min} \min \argmin_{k} \{{\rm lcm} \{a+k, b+k\}\}を求めて出力してAC。a,b\le 10^9だがO(\sqrt{|a-b|})なので間に合う。

拙解 (C++14): Submission #53247753 - Codeforces

D - Neko and Aki's Prank (2000点)

問題: Problem - D - Codeforces
コンテスト中には解けなかった。
長さ2nの括弧列全体からなるTrie木の辺をすべての辺が\deg \le 1になるように塗っていく問題。すべての葉の深さが2nで一定なことと、対称性をもつことによって、
\displaystyle dp[i][j][k]:=i個の'(', j個の')'があるときに親とのエッジを青く塗ったか(k=1)、塗っていないか(k=0)
で、交互に塗るよう遷移して、根ノードの親は実際には存在しないことを考慮しつつk=1の項をすべて足し合わせて、根ノードの子を塗るか塗らないか2通り試してAC。O(n^2)だがn\le 1000なので間に合う。

f:id:aprilganmo:20190427105740p:plain
括弧列の上下を斜めにしてdp

拙解 (C++14, コンテスト終了後): Submission #53264485 - Codeforces

E以降

見てません

まとめ

D問題が括弧列の+1,-1するやつを斜め45度に倒して階段状の格子路の経路問題に落とし込むのはうまいなと思いました