これは実際には興味深い問題です。コインごとに確率が異なるというOPの状況に至るまで、公正なコインと不公正なコインのトスを詳細にカバーするブログ投稿を書くように促されました。この問題を多項式時間で解決するには、動的計画法と呼ばれる手法が必要です。
一般的な問題:C、一連のn個のコインp1からpnが与えられた場合、p iはi番目のコインが頭に浮かぶ確率を表します。k個の頭がすべてのコインを投げることから浮かび上がる確率はどれくらいですか?
これは、次の漸化式を解くことを意味します。
P(n、k、C、i)= p i x P(n -1、k -1、C、i +1)+(1- p i)x P(n、k、C、i +1)
これを行うJavaコードスニペットは次のとおりです。
private static void runDynamic() {
long start = System.nanoTime();
double[] probs = dynamic(0.2, 0.3, 0.4);
long end = System.nanoTime();
int total = 0;
for (int i = 0; i < probs.length; i++) {
System.out.printf("%d : %,.4f%n", i, probs[i]);
}
System.out.printf("%nDynamic ran for %d coinsin %,.3f ms%n%n",
coins.length, (end - start) / 1000000d);
}
private static double[] dynamic(double... coins) {
double[][] table = new double[coins.length + 2][];
for (int i = 0; i < table.length; i++) {
table[i] = new double[coins.length + 1];
}
table[1][coins.length] = 1.0d; // everything else is 0.0
for (int i = 0; i <= coins.length; i++) {
for (int j = coins.length - 1; j >= 0; j--) {
table[i + 1][j] = coins[j] * table[i][j + 1] +
(1 - coins[j]) * table[i + 1][j + 1];
}
}
double[] ret = new double[coins.length + 1];
for (int i = 0; i < ret.length; i++) {
ret[i] = table[i + 1][0];
}
return ret;
}
これが行っているのは、 piからpnまでのコインのシーケンスにk個のヘッドが含まれている確率を示すテーブルを作成することです。
二項確率のより深い紹介と動的計画法の適用方法に関する議論については、コイントス、二項式、および動的計画法を参照してください。