CS Academy #14 - Subarrays Xor Sum
問題
問題概要
長さの数列が与えられる。長さが以上以下の部分列に対して、xorを取った値の和をで割った余りを答えよ。
アイデア
ビットごとに独立に考えていく。今、ビットを固定する(とする)と、もとの数列は01の数列として見なすことができるようになる((a[i]>>b)&1
)。
こうなると、このビット列の中の部分列の中で、xorの値が1になる個数を数えるという問題に答えれば良いということになる。
さて、一般的な数列の部分和と同じように数列の部分に対してxorをとったものも同様に計算できる。からの部分和が欲しければ、prefix sum()を用意しておいてそのとに注目すれば良い。
次に、この部分列の長さに対する制約(以上以下)をどのように対処するかを考える。 個数を数えるにあたって、部分列の区間の右を固定して考える。すると、この部分列の制約から区間の左のindexはからということになる。つまり、の値に注目して、区間]のpreに対して0と1の値が何個ずつあるかを保持しながら、を増やしていくことで、この更新の処理を尺取的にできるので1つのビットに対してで計算ができ、十分に間に合う。
実装(C++)
続きを読むCS Academy #20 - Palindromic Concatenation
問題
問題概要
文字列が個与えられる。番目の文字列をと表す時、との連結(この順番に並べて結合した文字列)が回文になるような組の個数を求めよ。
- は英小文字のみで構成される
- とは区別される
アイデア
が回文になる時、どのような状況になれば条件を満たすかを考えてみる。この条件は文字列の長さに依存するので、以下のように3つに条件を分けて考える:
1のときに満たすべき条件はシンプルで、をreverse
したらに一致することである。
次に、2のときに満たすべき条件を考えてみる。の方が短いので、回文の中心はの途中の位置に来ることになる。よって、それぞれの文字列の長さをとおけば
- を
reverse
した文字列との末尾から文字が一致 - の先頭から文字が回文になっている
という2つの条件を同時に満たす必要があることが分かる。
3についても対称に考えれば、
- を
reverse
した文字列との先頭から文字が一致 - の末尾から文字が回文になっている
という2つの条件を同時に満たす必要があることが分かる。
の制約から、それぞれのペアをとってきて比較するということは間に合わなさそうなので、別の方針を考える必要がある。 そこで、ハッシュ値を利用して各とペアを作ることが出来る文字列の個数を探す。
条件1に関しては、各文字列をreverse
したときのハッシュ値をカウントしておけば簡単に計算できる。以下では2,3について考える。
まず、個の文字列は長い方から順に処理していくことにする。そして、mapにハッシュ値をカウントしていく。そのときに、先頭から文字が回文になっていれば残りの末尾の文字のハッシュ値を+1し、末尾から文字が回文になっていれば残りの先頭の文字のハッシュ値を+1とする。
この、「回文になっているかどうか」という判定は、各文字列に対して元の文字列と、reverse
した後の文字列でそれぞれローリングハッシュを構築し、そのハッシュ値の比較をすることでで判定することが可能になる。
各文字列に対して、ペアを作ることが出来る文字列の個数はこのをreverse
したもののハッシュ値のカウントに一致する。