2020年5月11日月曜日

CodeChef May Challenge 2020 - Chef and Rainbow Road

要約: a1,...,aNa_1, ..., a_Nから (1) 重複を許して選んで (2) どれも少なくとも1個以上選んで (3) 合わせてN+K1N+K-1個になるように選んで、積を取るとする。それらの総和を求めよ。

最低11個以上という条件を外してK1K-1個選ぶことにして、求まった値にa1...aNa_1...a_Nを掛ければよい。

多項式で考えるんだろうなという検討はつくが、ほとんど何も知らないのでmaspyさんの記事などを見て式を考える。とりあえず

(1+a1x+a12x2+...)(1+a2x+a22x2+...)...(1+aNx+aN2x2+...)(1+a_1x+a_1^2x^2 + ...)(1+a_2x+a_2^2x^2 + ...) ... (1+a_Nx+a_N^2x^2 + ...)

の第K1K-1項(0-based)を見ればよいことがわかる。この式は((1a1x)(1a2x)...(1aNx))1((1-a_1x)(1-a_2x)...(1-a_Nx))^{-1}と表せて、(1a1x)(1a2x)...(1aNx)(1-a_1x)(1-a_2x)...(1-a_Nx)は分割統治してFFTすればよく、逆元もFFTで求まるらしいので、K105K \le 10^5の部分点1, 2はそれで取れる。

部分点3からはこの方針では無理そう。ところで、この間のlong challengeのまったく歯が立たなかった問題についてNyaanさんが記事を書いていたのを思い出して見に行ったら、部分分数分解というワードが出てきて使えそうと思う。

1(1a1x)(1a2x)=a1(a1a2)(1a1x)+a2(a2a1)(1a2x) \frac{1}{(1-a_1x)(1-a_2x)} = \frac{a_1}{(a_1-a_2)(1-a_1x)} + \frac{a_2}{(a_2-a_1)(1-a_2x)}

と分解できるので、全部掛けると1/(1a1x)1/(1-a_1 x)の係数はa1N1/j1(a1aj)a_1^{N-1}/\prod_{j \neq 1} (a_1 - a_j)になる。対称性により1/(1aix)1/(1-a_i x)の係数はaiN1/ji(aiaj)a_i^{N-1}/\prod_{j \neq i} (a_i - a_j)であり、これが1+aix+ai2x2+...1+a_i x + a_i^2 x^2 + ...に掛かっているのでxK1x^{K-1}の係数はaiK+N2/ji(aiaj)a_i^{K+N-2}/\prod_{j \neq i} (a_i - a_j)とわかる。この値をすべてのiiについて加算すれば答えが得られる。部分点3が取れた。

満点について。aiK+N2/ji(aiaj)a_i^{K+N-2}/\prod_{j \neq i} (a_i - a_j)の分母の形を見るとヴァンデルモンド行列式やラグランジュ補間などが思い浮かぶので、ラグランジュ補間の解説を読んでいて(xa1)...(xaN)(x-a_1)...(x-a_N)を微分したものに代入すればいいと気づく。多項式の値をNN個の点について求める必要があるが、ググるとO(Nlog2N){O}(N\log^2 N)でできるらしい → 間に合った。


最終日に満点に気づいた。時間がなさすぎたのでbeetさんのライブラリを大急ぎで写経…… 長期コンテストでも終了直前に方針が立つと結局時間に追われることになるな。