Codeforces Round #635 (Div. 1) E1. Chiori and Doll Picking (easy version)
E1しか解けていないので、E1しか通らない解法を書きます…。この他にも色々な解法があるっぽい?
問題概要
個の非負整数 が与えられる。また非負整数 が与えられ、 である。
から任意個の要素を選ぶ選び方は全部で 通りある。選んだ要素のXOR和の立っているビット数が であるような選び方の個数を、 の全てに対して で求めよ。
制約(E1)
解法
初手は掃き出し法
「 個の要素から任意個選んでXOR和を取る」という操作を考える上で強力な道具が、 上での線形代数、特に「掃き出し法」です。このブログでもいくつかの問題で解説を書いています。
- yukicoder No.803 Very Limited Xor Subset - ARMERIA
- AtCoder Beginner Contest 141 F - Xor Sum 3 - ARMERIA
各 を行、各ビット桁を列とする行列を考え、行基本変形による掃き出し法を行うと、答えを変えないまま以下の性質を満たす行列に変形できます。
- ゼロでない行(基底)として残る の個数は、ビット桁数以下である。
- 各ビット桁について、その桁を最上位ビット桁(MSB)とする は高々1つである。
ゼロになった要素が 個ある場合は、それらを無視して計算し、最後に全ての答えに を掛ければ良いです。以降は基底となった高々 個の要素について考えます。
MSBで半分全列挙
一番下の桁を 桁目と書くことにします。 桁目は に対応する桁です。
E1の制約において最も大きい桁は 桁目です。ここで 桁目を「下位ビット」、 桁目を「上位ビット」と呼ぶことにします。
この解法のアイデアとしては、基底を
- グループ :MSBが上位ビットであるもの
- グループ :MSBが下位ビットであるもの
の2グループに分けて半分全列挙をします。「各桁をMSBとする は高々1つである」という性質により、両方のグループの要素数は18個以下です。またグループ の上位ビットは全て です。
重要な視点は、グループ の列挙結果とグループ の列挙結果をマージする際に上位ビットが干渉することはない、ということです。つまりグループ について全列挙した時点で、上位の具体的なビット列は忘れてしまって立っている個数だけを保持しておけば良い、ということが言えます。
具体的には全列挙によって以下の値を集計することになります。
- グループ の基底の選び方のうち、そのXOR和において上位ビットの立っている個数が で、下位ビット列が であるものの個数
- グループ の基底の選び方のうち、そのXOR和において下位ビット列が であるものの個数
各 について別々に、 と をマージします。これは をXOR演算の記号として
となるような数列 を求めることになり、俗に添字XOR畳み込みと呼ばれています。これは「高速アダマール変換」と呼ばれるもので計算できます。
これが計算できれば、 を に足し込んでいけば良いです。ここで はビット列 の立っているビットの個数、 は答えとなる数列を表すことにします。
これを全ての について計算し終わったら、最後に掃き出した分の を掛けて完了です。
計算量は、まず掃き出し法が です。ただし ビットの整数のXORを とみなせば です。後半パートは として、高速アダマール変換を 回するところが一番重くて になります。