TopCoder SRM 641 Hard
2017-02-15 |
[Competitive programming]
概要
n (1 <= n <= 20) ビットのビット列に対し,「一様ランダムに 1 ビット選んで反転する」を繰り返す.
ビット列にはカーソルがあり,ビット反転を行うためには反転したいビットまでカーソルを動かす必要がある.
カーソルの移動には,位置の差の絶対値に等しいコストがかかる.
ビット列のすべてのビットが同じになったら操作は終了である.
ビット列 (n は固定),最初のカーソルの位置が与えられたとき,操作が終了するまでにかかるコストの期待値を求めるクエリを 1000 個処理せよ.
解法
「位置 i にいる状態から位置 j に移動してビット j を反転する」が行われる回数の期待値を求められればよい(各 i, j に対し,この期待値を重み |i - j| を掛けて足し合わせる).
2^n 通りのビット,現在のカーソル位置 n 通り全部に対して遷移を考えて,連立方程式を解けばこれは求められるが,明らかに計算量が大きすぎる.
ここで,この期待値を求めるためには,「位置 i のビットの値」「位置 j のビットの値」「カーソル位置が i か?」「位置 i, j 以外のビットで 1 が立っている個数」にだけ注目すれば十分である.
この場合の状態数は 8(n+1) になり,遷移をすべて考慮して連立方程式を解いても (1 回だけなら) 十分間に合う.
さらに,この連立方程式を 1 回解けば,複数の i, j や複数の初期ビット列に対しても結果を使いまわすことができる.
最初の連立方程式の計算は O(n^3) (ただし,定数 512 がある) であり,各クエリの処理は O(n^2) なので,十分間に合う.
コード