Australia

ウォンバットのブログ

CODE FESTIVAL 2018 qual A C - 半分

解法

 A_i=0になったら、それ以降は 2で割らないものとします。そうすると、求める答えは本来の「 K回の操作後の数列としてありうるものの個数」に「 K回未満の操作後の 0 1つ以上含む数列としてありうるものの個数」を加えたものになります。

 dp[i][j][k]:= A_1から A_iまで考えたときの、 j回操作してできる数列の個数( kはそれまでの要素に 0があったかどうかのフラグ)

というDPを考えれば、 A_i 2 c_i回割ると 0になるとして、

 dp[i][j][0]=\displaystyle \sum_{j'=j-c_i+1}^{j} dp[i-1][j'][0]
 dp[i][j][1]=\displaystyle \sum_{j'=j-c_i}^{j} dp[i-1][j'][1]+dp[i-1][j-c_i][0]

と遷移が定義できます。あとはここから適切に値をとってきて足し合わせればよいです。
計算量は O(N^2 (\log \max A_i)^2)になります。

反省

DPをDPだと気づくのはけっこう速くなったような気がしますが、詳細を詰めるのが苦手です。