2020年1月24日金曜日

ARC 070 D - No Need

xx枚目まで見たときに総和がyy以上になるようなカードの集合の総数をdp[x][y]dp[x][y]とすると、漸化式は

dp[x][y]=dp[x1][y]+dp[x1][yax] \operatorname{dp}[x][y] = \operatorname{dp}[x-1][y] + \operatorname{dp}[x-1][y-a_{x}]

となる。ここで、NN番目のカードとii番目のカードを入れ替えて同じDPをしたものをdpi\operatorname{dp}_iとする。dpi\operatorname{dp}_iについても同じ漸化式が成立し

dpi[N][y]=dpi[N1][y]+dpi[N1][yai] \operatorname{dp}_i[N][y] = \operatorname{dp}_i[N-1][y] + \operatorname{dp}_i[N-1][y-a_i]

順番を入れ替えてもNN枚処理すれば同じ結果になるはずだからdp[N][y]=dpi[N][y]\operatorname{dp}[N][y] = \operatorname{dp}_i[N][y]が成り立つ。したがって

dp[N][y]=dpi[N1][y]+dpi[N1][yai] \operatorname{dp}[N][y] = \operatorname{dp}_i[N-1][y] + \operatorname{dp}_i[N-1][y-a_i]

整理して

dpi[N1][y]=dp[N][y]dpi[N1][yai] \operatorname{dp}_i[N-1][y] = \operatorname{dp}[N][y] - \operatorname{dp}_i[N-1][y-a_i]

という漸化式が立つ。ii番目のカードを除いたとき和がyy以上になるような集合の総数をf[i][y]f[i][y]とするとf[i][y]=dpi[N1][y]f[i][y] = \operatorname{dp}_i[N-1][y]だから

f[i][y]=dp[N][y]f[i][yai] f[i][y] = \operatorname{dp}[N][y] - f[i][y-a_i]

dp\operatorname{dp}を求めた後、さらにffについてDPできる。

カードiiが不必要
\Leftrightarrow カードiiを含む和がKK以上になるような集合と、カードiiを含まない和がKK以上になるような集合が一対一対応する
f[i][K]=dp[N][K]f[i][K]\Leftrightarrow f[i][K] = \operatorname{dp}[N][K] - f[i][K]

だから、この等式が成立するようなiiを数えればよい。

dp\operatorname{dp}の値は64ビットに収まらないので、適当にmodをとって扱う。弱衝突耐性があれば十分なので32ビットでよさそう。だめなら複数modを組み合わせればよい。


戻すDPを覚えるために復習。

参考: https://sen-comp.hatenablog.com/entry/2019/11/06/121325