月刊組合せ論 Natori は面白そうな組合せ論のトピックを紹介していく企画です。今回は転倒数が k に等しい順列の個数を求めたいと思います。
転倒数
#
長さ n の順列とは (1,2,…,n) の順列のこととします。
順列 p=(p1,p2,…,pn) の転倒数とは、1≤i<j≤n かつ pi>pj をみたす組 (i,j) の個数です。例えば順列 (1,4,2,3) の転倒数は 2 です。
転倒数が k の順列を構築する問題を紹介します。(厳密には順列ではないですが、似たようなものです。)
https://yukicoder.me/problems/no/1619
この記事では構築ではなく数え上げを考えていきます。
長さ n の順列であって転倒数が k であるものの個数を b(n,k) とおきます。表は次のようになります。
n\k |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
1 |
1 |
|
|
|
|
|
|
|
|
|
|
2 |
1 |
1 |
|
|
|
|
|
|
|
|
|
3 |
1 |
2 |
2 |
1 |
|
|
|
|
|
|
|
4 |
1 |
3 |
5 |
6 |
5 |
3 |
1 |
|
|
|
|
5 |
1 |
4 |
9 |
15 |
20 |
22 |
20 |
15 |
9 |
4 |
1 |
この表を見て簡単に気が付くことがあります。
- b(n,k)=0 となる k の最大値は 2n(n−1) : 転倒数が最大となるのは (n,n−1,…,2,1) のときだからです。
- 左右対称 : 順列を反転させる行為が全単射になります。
次の節では具体的に値を求める方法を考えていきます。
動的計画法
#
転倒数が k である長さ n+1 の順列の個数 b(n+1,k) を動的計画法で求めます。(すなわち漸化式を求めます。)
長さ n+1 の順列は長さ n の順列に n+1 を挿入することで得られます。
n+1 を右端に挿入すると転倒数は増えず、右端から 1 つ隣に挿入すると転倒数は 1 増加し、…、左端に挿入すると転倒数は n 増加します。
このことから、長さ n+1 で転倒数が k である順列は長さ n で
- 転倒数が k の順列
- 転倒数が k−1 の順列
- …
- 転倒数が k−n の順列
に挿入を行うことで得られます。これより、漸化式は
b(n+1,k)=b(n,k)+b(n,k−1)+⋯+b(n,k−n)となります。これで、時間計算量 O(n2k) の解法が得られました。
ここで k を k−1 に置き換えた式
b(n+1,k−1)=b(n,k−1)+⋯+b(n,k−n)+b(n,k−n−1)に注目すると
b(n+1,k)=b(n+1,k−1)+b(n,k)−b(n,k−n−1)という漸化式が得られます。これで時間計算量 O(nk) で求めることができます。
母関数
#
みんな大好き母関数を考えましょう。inv(p) を p の転倒数として
fn(z)=k=0∑n(n−1)/2b(n,k)zk=p∈Sn∑zinv(p)とおきます。漸化式
b(n+1,k)=b(n,k)+b(n,k−1)+⋯+b(n,k−n)を用いると
fn+1(z)=k≥0∑b(n+1,k)zk=k≥0∑(b(n,k)+b(n,k−1)+⋯+b(n,k−n))zk=k≥0∑b(n,k)(zk+zk+1+⋯+zk+n)=(1+z+z2+⋯+zn)k≥0∑b(n,k)zk=(1+z+z2+⋯+zn)fn(z)となるので、これより
fn(z)=(1+z)(1+z+z2)⋯(1+z+z2+⋯+zn−1)となります。これは n の階乗の q 類似となっています (ここでは q ではなく z を用いていますが)。
この等式を組合せ論的に解釈してみましょう。1,2,…,n の順に挿入していくことで順列を作ります。まず 1 を置きます。2 を挿入するとき、1 の右にするか左にするかによって、転倒数が 0 または 1 増えます。これが (1+z) に対応します。3 を挿入するとき、どの位置に挿入するかによって転倒数が 0,1,2 のいずれかの値だけ増えます。これが (1+z+z2) に対応します。このようにして上の等式を得ることもできます。
オイラーの五角数定理
#
【月刊組合せ論 Natori】ヤコビの三重積公式とオイラーの五角数定理【2023 年 2 月号】で紹介したオイラーの五角数定理は次の等式です。
(1−z)(1−z2)(1−z3)⋯=j∈Z∑(−1)jz(3j2+j)/2この式を g(z) とおきます。
転倒数と五角数
#
b(n,k) の母関数は
fn(z)=(1+z)(1+z+z2)⋯(1+z+z2+⋯+zn−1)=j=1∏n1−z1−zjでした。gn(z)=∏j=1n(1−zj),hn(z)=(1−z)−n とおくと、fn(z)=gn(z)hn(z) です。fn(z) における zk の係数 b(n,k) を求めたいです。
n≥k を仮定すると、gn(z) を g(z) に置き換えてもよいです。すなわち g(z)hn(z) における zk の係数も b(n,k) です。g(z) は上述の通りです。hn(z) は負の二項定理より
hn(z)=(1−z)−n=k≥0∑(kn+k−1)zkと表せます。これらを合わせると、b(n,k) は次のように表せることがわかります。
定理: n≥k とする。転倒数が k である長さ n の順列の個数は
b(n,k)=j∑(−1)j(k−djn+k−dj−1)に等しい。ここで j は五角数 dj=(3j2+j)/2 が k 以下となる範囲を動く。
なお競技プログラミングにおいては、(1−z)(1−z2)⋯(1−zn) を形式的べき級数の exp, log を用いて計算することで b(n,k) を求めることができるそうです。この方法は n≥k でない場合も使えます。
おわりに
#
順列の世界は奥深いですね。
長らくおやすみをいただいていた月刊組合せ論 Natori ですが、ようやく復活することができました。更新は不定期になるかもしれませんが、今後も応援のほどよろしくお願いします。
参考文献
#
- Bóna, Miklós. Combinatorics of permutations. 3rd ed.