問題概要
整数 と、整数の組
が
個与えられる。以下の条件を満たす長さ
の整数列
の個数を
で求めよ。
- 全ての要素は
を満たす。
- 整数の組
で表現される以下の条件を
個全て満たす。
のビットANDを取った値がちょうど
となる。
制約
解法
※解説・実装の都合上、 のインデックス
を1-indexedのまま扱うことにします。
この問題はビット桁ごとに独立に考えることができます。つまり一番下のビット桁を 桁目として、
についてそれぞれ「
の
桁目の並びに相当する、
または
からなる長さ
の数列」の選び方を独立に求め、掛け合わせたものが答えになります。
具体的には ビット目を考える時には条件
は以下のようになります。そして全てのビット桁においてこれらの条件が全て満たされることが問題の条件を満たす必要十分条件になります。
の
ビット目が
であれば、条件は「
の
ビット目が全て
である」こと。
の
ビット目が
であれば、条件は「
の
ビット目の少なくとも1つが
である」こと。
以降はある1つの桁についての数え上げパートを考え、 の該当桁の値(
または
)を単に
と表記します。
まずは「区間内が全て 」タイプの条件に基づいて、各インデックス
が「必ず
にならないといけない」かどうかを求めておきます。こちらのタイプに属する条件区間
全ての和集合を取れば良いので、imos法を使うことで全てのインデックスについてまとめて計算することができます。
次は「区間内の少なくとも1つが 」タイプの条件を上手く扱いながら数え上げていきます。準備としてこちらのタイプに属する条件区間
を列挙し、右端
ごとに分類しておきます。
結論から言うと、次のようなDPを考えれば良いです。
ただし が1度も登場していないようなものは
として扱うことにします。
ちょっとややこしいですが、最後に登場した の位置で分類して数えているというところがキモです。この
への遷移を考える時には、
である
に対して、
として数えられている数列
について「
から
までを
で埋めて、
を
にする」と続けるような遷移をすることになります。
具体的な遷移計算を考えます。まず が先ほどの「必ず
にならないといけない」インデックスだった場合は必ず
です。
そうでない場合、遷移元として選べる は、
から
までを
で埋めても「区間内の少なくとも1つが
」タイプの区間を塞がないようなものです。つまり区間のうち
であるものに対する
の最大値を
とすると、遷移元として条件違反にならないのは
の範囲です。
このように、遷移元となるのはある区間における の和です。そのためDPテーブルを埋めながら同時に累積和も求めておくか、
が単調増加であることを利用してしゃくとり法のように
からの区間和の値を管理することで効率的に計算できます。
まで埋め終わったら、
として
であるような
の合計が求めるべき場合の数になります。正しくは、
として数えられている数列
について
を全て
で埋めたものを数えていることになります。
これを全ビット桁について繰り返すので、 を紛れ込ませずに上手く実装すると計算量は
になります。制約が大きめなので、区間和を取るのにセグメント木やBITなどを用いると厳しいかもしれません。