AtCoder Beginner Contest 134 F - Permutation Oddness
※問題文で与えられている は小文字ですが、 を添え字として使いたいので本記事では と表記します。
解法
順列のDP
順列の場合の数を求める問題です。何か条件を満たす数列の個数を求める問題として「左からDP」というのはメジャーな解法ですが、順列の場合は各数字をちょうど1回しか使えないという性質のためDPがやりにくいです。例えば
- 左から 番目の場所まで決めて、既に使った整数の集合が で、それまでの奇妙さの合計が である場合の数
みたいなのを考えてDPすることは一応できるのですが、これは結局bit DPなので が大きいと状態数が爆発してしまいます。
なので順列の数え上げについては、
- そもそもDPしない、数学などでがんばる
- 使った整数の集合を具体的に覚えておかなくていいDPを組む
などの工夫が必要になります。後者として例えば挿入DPがあり、これはDPで持つ情報を「数の集合」ではなく「ある条件を満たす場所の個数」として持つようなDPです。このように何かの「個数」で状態を持つことができれば状態数を抑えることができます。
今回の問題も、そのような方針でDPを組むことができます。
箱根駅伝DP
この問題に由来して、俗に「箱根駅伝DP」と呼ばれているテクニックです。
整数 までの各整数について、以下のように「箱」と「ボール」を考えます。最初にそれぞれの箱に、仮で同じ番号のボールを入れておきます。
この箱とボールの組を左から見ていきながら、箱にボールを入れたり入れなかったりします。まず最初の箱1+ボール1については、
- 箱1にボール1を入れる。
- 箱1にボール1を入れない。ボール1が「保留ボール」として残り、箱1も「保留箱」として残る。
の2パターンがあります。
次の箱2+ボール2について。もし箱1にボール1を入れていた場合は全く同じ2パターンを考えれば良いですが、保留があった場合には事情が異なります。つまり上の2パターンに加えて、
- 箱2に保留ボール1を入れて、ボール2を保留にする。
- 箱2に保留ボール1を入れて、保留箱1にボール2を入れる。
- 箱2を保留にして、ボール2を保留箱1に入れる。
の3つ、合計5パターンがあります。
この遷移をDPで扱っていきます。このとき保留にしているボールや箱を集合で持つとやっぱり状態数が爆発しますが、これを「個数」だけで上手く扱います。保留しているボールと箱の個数は等しいので、
- 左から 番目の場所(箱+ボール)まで見終わって、保留しているボールと箱の個数がともに 個で、それまでの(?)奇妙さの合計が である場合の数
というDPを考えることができます。順列が完成しているときにはもちろん保留がゼロなので、答えは として求められるでしょう。
先ほどの5パターンについて、遷移にかかる係数と の増減はそのまま求めることができます。保留箱や保留ボールを選ぶたびに場合の数には 倍の係数が掛かり、パターンによって遷移後の が のいずれかになります。以下の図で列挙します。
ただ1つ困ったことがあり、それは図中でも?と記載している の更新です。箱にボールを入れた時に奇妙さを直接足そうとすると、箱とボールの具体的な数字が分からないと求められません。その扱いを詰められればゴールです。
奇妙さ の更新
の更新ですが、イメージは を1個進めるたびに奇妙さを「積み立てておく」感じです。具体的に説明します。
保留ボールとしてボール 、保留箱として箱 があったとします。そしてDPにおいて、 番目の場所を見ているものとします。ここで かつ です。
ここでもし箱 に保留ボール を入れれば奇妙さは 増えます。また、保留箱 にボール を入れれば奇妙さは 増えます。これらは「今入れたときに増えるはずの奇妙さ」です。
しかしここでどちらも入れなかったとしましょう。そして見ている場所を 番目にずらすと、さきほどの「今入れたときに増えるはずの奇妙さ」はそれぞれ1ずつ増えることになります。
このように、箱やボールが保留されている状態で見ている場所をずらすたびに奇妙さを1ずつ足していくのが「積み立て」の考え方です。つまり保留箱と保留ボールがともに 個の状態で見ている場所 を1つずらすときに、奇妙さ に を加算してしまうことで、奇妙さの合計を正しく管理することが出来るのです。
場所 を見ているときにボール や箱 を保留にしても、その時点では「今入れたときに増えるはずの奇妙さ」は0なので特に足す必要はありません。つまり先ほどの図で?と記していた遷移先の奇妙さの値は、全て とすることができます。先ほどの図に合わせて言えば、見る場所を とずらしたときに増える分ということになります。
これで全ての遷移が完成しました。状態数 であり、遷移は高々5パターンなので全体計算量も同様のオーダーになります。