重複組合せ

以前友人から重複組合せ(repeated combination)の質問を受けたので今回はそのお話です
あんまり構造力学と関係ないかもですが・・・(´・ω・`)


まずは重複を持たないフツーの順列・組合せについて
combination.wxm

%o1にてパッケージ"functs"をロードします(画面出力は省略)
Warning以下の文言は最大公約数を返す関数lcmについての注意書きで,今回は特に問題ありません
%o2にてパッケージ"simplify_sum"をロードします(画面出力は省略)
%o3および%o4にてそれぞれ順列・組合せを返す関数を定義します
異なる n個のものから m個のものを選ぶ順列Pおよび組合せCをそれぞれ%o5,%o6式に示します
ちなみに出力は二項係数(binomial coefficient)で表されます
順列Pと組み合わせCには%o7の関係が成り立ちます



重複順列(repeated permutation)を返す関数Πを%o9式で定義します
実際に6個から重複を許して2個取り出す順列を%o10式に示します



さて本題の重複組合せですが,重複順列ほど簡単ではありません
結論から書きますが,n個に重複分として追加したr-1個からいくつ取り出すか(0も含めて)で場合分けを行い
それら各々の組合せをすべて足し合わせた算式を%o12式に示します
二項係数で書き直した結果を%o13式に示します
重複組合せを返す関数Hを,総和についてさらに書き下した結果を用いて%o14式で定義します
実際に6個から重複を許して2個取り出す組合せを%o15式に示します



結局何をしているかというと,追加分を合わせた n+r-1個から r個を取り出す組合せと等しく成ります(%o16)
同様にしてH(6, 2)が%o15と同じ値を返すことを確認します(%o17)


私が高校生の時には確か仕切り分配法を使って説明されたような記憶があります(´-`).。oO


追記
具体的なイメージとしては,2つのサイコロを振った時の出目のパターンについて

  • Π(6, 2)は"サイコロの見分けが付く"場合を
  • H(6, 2)は"サイコロの見分けが付かない"場合を,それぞれ考えることになります