鍋あり谷あり

テーマを決めずに適当に書いています。

ダイスで組み分けこれで最後かな

d:id:Nabetani:20070820, d:id:Nabetani:20070822, d:id:Nabetani:20070823, d:id:Nabetani:20070827 の続き。
数式の形で表すのは面倒なので、ruby のソースで:

require 'rational'

def dc( people, non, one, twomore )
  (@h||={})[[people, non, one, twomore]]||= # cache.
  if people==0 && one==0 && twomore==0
   1
  else
    r = (0..people)
    if ! r.include?( one ) || ! r.include?( twomore ) || non<0
      0
    else
      ( non+1 ) * dc( people-1, non+1, one-1, twomore ) +
      ( one+1 ) * dc( people-1, non, one+1, twomore-1 ) +
      ( twomore ) * dc( people-1, non, one, twomore )
    end
  end
end

N=6

(1..ARGV[0].to_i).each{ |pe|
  s = (0..N).inject(0){|sum,i|
    sum += dc(pe,i,0,N-i)
  }
  puts( "%3d : %s"%[pe,1-Rational(s)/N**pe] )
}

見ての通り、漸化式になっている。そして、フィボナッチの列と同様、行列の積の形に書き直すことができる。そうすると、先日書いた A(M**n)S という形になる。この式は簡単な式に見えるが、M は30×30の行列(6面ダイスの場合)になる。行列が巨大なので素直に計算すると大変だが、Mはたぶん対角化することができる。指数の線形和みたいな形の一般項も求まるんだと思う。
関数 dc は、dc(人数, まだ出てない目が何個あるか, ひとりグループが何個あるか, 二人以上のグループが何個あるか) ということ。素直に漸化式になっている。

それとは別に、d:id:Nabetani:20070823 で書いた計算。D面ダイスで、n人だと

\bigsum_{1\leq i \leq D, i \leq n}\frac{D!n!{(D-i)}^{n-i}(-1)^{i+1}}{(D-i)!i!(n-i)!}

こんな感じ。
あーこの式は、場合の数。題意の通りの確率にするには D**n で割ればいい。
この式に至る経緯はちょっと説明が面倒なんだが、場合の数の計算そのまんま。A君がひとりグループになる場合、A君とB君がひとりグループになる場合、A君B君C君がひとりグループになる場合……と足したり引いたりした結果である。

で。
どっちが一般項らしいかという話なんだが。
それは私にもよくわからない。