AtCoder Regular Contest 058:E - 和風いろはちゃん / Iroha and Haiku
問題
https://atcoder.jp/contests/arc058/tasks/arc058_c
考え方
考えていたこと
条件を満たす数列はどのような数列であるか考えた。
を全探索する。そのとき
の区間の長さを求めておいて、各区間の長さの要素の和が
なる要素の組み合わせを考えると、これは重複組合せで求めることができる。範囲に含まれない要素は
の任意の数を選択できる...
みたいな考察を進めていた。がサンプル3で合わず。よく考えると、範囲外の要素で XYZ
の数列が含まれるので数列を重複して数えていることになる。
解説見た
余事象の数え上げを考える。余事象のほうが数え上げやすいため。数列の要素ごとに左から全探索していくことを考える。例えば という
XYZ
の組み合わせを考えると、X Y
が決まっていたとすると、どういうときに次の数 Z
を選べないか。
それまでの数字の和が 1 2
となる場合は次に Z
として 1
をとることはできない。 XYZ
が 121
になってしまうため。
数列の状態を bit で考えることにしよう。 であるから
として状態を持つことができる。
今までの数列の和の状態が左から 1 2
となる場合に bit として となっているとしよう。このように bit で状態をもつことを考えることがこの問題を bitDP で解くために重要な考察な気がする。このとき
として
をとることを考えると bit の状態は
となる。これは bit の下位(0-indexed)から考えて
となっているので状態として遷移することができない。そうでない場合、例えば
などを選ぶ場合は
となるので遷移することができる。
よって次のようなメモ化全探索を考えよう
桁目まで考えて数列の状態が
であるような場合の数
DP遷移は 桁目に数
をとるとすると
next = state << j | 1 << j - 1
となる(実装のまんま)。これが XYZ
にならないとき、つまり next >> z - 1 && next >> y + z - 1 && next >> x + y + z - 1
にならないときのみ遷移可能
Submission #4328265 - AtCoder Regular Contest 058
何がバグっていたか
- ダブって数え上げしてしまう
得た知見(典型ポイント)
- 余事象を考える
- 状態を bit でもって全探索
類題
- D - ディスクの節約 bitDPという意味で