这实际上是一个有趣的问题。我受到启发写了一篇关于它的博客文章,详细介绍了公平与不公平的硬币投掷,一直到 OP 的情况,即每枚硬币都有不同的概率。您需要一种称为动态规划的技术来在多项式时间内解决此问题。
一般问题:给定C,一系列n个硬币p1 到 pn 其中 pi em> 表示第 i 个硬币正面朝上的概率,抛完所有硬币后第 k 个正面朝上的概率是多少?
这意味着解决以下递归关系:
P(n,k,C,i) = pi x P(n-1,k-1,C,i+1) + (1-pi) x P(n,k,C,i+1)
执行此操作的 Java 代码 sn-p 是:
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 个头。
如需更深入地介绍二项式概率以及如何应用动态规划的讨论,请查看Coin Tosses, Binomials and Dynamic Programming。