2019年4月20日土曜日

天下一プログラマーコンテスト 2019 D - Three Colors

天下一プログラマーコンテスト D - Three Colors

S=iaiS = \sum_i a_iとせよ。Rの和がS/2S/2以上だと三角形は作れないし、G、Bについても同様である。三角形を作れないような塗り方の総数は(Rの和がS/2S/2以上になるような塗り方)+(Gの和がS/2S/2以上になるような塗り方)+(Bの和がS/2S/2以上になるような塗り方)でだいたい求まるので、それを3N3^Nから引けば答えになる。「だいたい」というのは、SSが偶数の時は色Xの和がS/2S/2かつ色Yの和がS/2S/2であるような塗り方が存在するかもしれないので、上の式だと重複して数えてしまうことになるからである。

とりあえずSSが奇数の場合を考える。数列をa1,...,axa_1, ..., a_xに限定した時にRの和がuuになるような塗り方の総数をf(x,u)f(x, u)とすると、

f(x,u)=f(x1,uax)+2f(x1,u) f(x, u) = f(x-1, u-a_x) + 2f(x-1, u)

である。G、Bについても同じ数になるので、答えは

3N3u=S/2Sf(N,u) 3^N - 3 \sum_{u = \lceil S/2 \rceil}^S f(N, u)

であり、DPすれば良い。

SSが偶数の場合、重複して数えた分を引かなければならない。数列a1,...,axa_1, ..., a_xをX、Yの2色に塗り分けるとして、色Xの和がuuになるような塗り方の総数をg(x,u)g(x, u)とすると、

g(x,u)=g(x1,uax)+g(x1,u) g(x, u) = g(x-1, u-a_x) + g(x-1, u)
が成り立つ。上の式では、Rの和がS/2S/2かつGの和がS/2S/2、Gの和がS/2S/2かつBの和がS/2S/2、Bの和がS/2S/2かつRの和がS/2S/2という3つのパターンを2回数えているので、重複の総数は3g(N,S/2)3g(N, S/2)である。したがって、SSが偶数の場合の答えは
3N(3u=S/2Sf(N,u)3g(N,S/2)) 3^N - \Bigl( 3\sum_{u = S/2}^S f(N, u) - 3g(N, S/2)\Bigr)
になる。計算量はO(N2maxiai){\mathcal O}(N^2 \max_i a_i)

考察の序盤は、まず数列a1,...,axa_1, ..., a_xの塗り分けでRの和がuu、Gの和がvvになるようなものの総数をf(x,u,v)f(x, u, v)として考えていた。しかし、これではもちろん間に合わないしデータ構造による高速化も思いつけず、なんとかf(x,u)f(x, u)だけで済まないだろうかと悩んだ末に上の方針に思いいたった。補集合に注目するのが習慣化していればもう少し早く正解にたどり着けたかもしれない。