ツバサの備忘録

主に備忘録代わりに精進記録を載せていくつもりです。

AGC028 B - Removing Blocks

問題
提出コード

解法

サンプル2がすごい実験に使いやすいのでこれを利用していくことで解けました。
まず、a_{i}は、i番目が足される回数に最後に掛け合わせるだけでいいので、これ以降は無視をします。
ということで、i番目の数字が何回足されるか、を調べます。
memo[i][j] = i番目の数字が、n!回の試行においてj番目を取り除いたときに何回足されるか
とします。
memo[i][j]はもちろんn!になります。
i=1としてみます。
j=2のとき、jより先にiが取り除かれてはいけません。
このようなパターンは、ちょうど半分存在するので、
memo[1][2] = \frac{n!}{2}になります。
j=3のとき、3を取り除く前に、21が先に取り除かれてしまってはいけないので、
1,2,3のブロックの順列を考えると、
123, 132, 213, 231, 312, 321 の6パターンのうち2パターンであったときのみ3を取り除いたときに1の数が足されます。
これは全体で1/3なので、
memo[1][3] = \frac{n!}{3}になります。
同様のことを考えると、
memo[1][j] = \frac{n!}{j}になります。
iが2以降のときを考えていく必要があるのですが、iより右側と左側はそれぞれ独立に考えてしまっても問題ありません。
なので、結局は、i=1と似たようなことが起きていて、
memo[i][j] = \frac{n!}{|i-j|+1}
という式が完成します。
あとはこの式の計算量を落とせば完成になります。
具体的には、memo[1][j]の総和を愚直に求めた後は、iが増えたときに先頭と末尾の2つの要素のみを入れ替えればいい(スライドしていくイメージです)ので、O(N)まで落とすことができます。
最後に、memo[i][j]iについての総和と、a_{i}の積をどんどん足していけば、答えが求まります。