sgu-508 Black-white balls 概率-贝叶斯公式
题意:有n个球,其中有0、1、2...n个黑球的概率是相等的,现在从中取出L个球,p个黑球q个白球。现在问猜一个黑球的区间,使得落在这个区间的概率大于给定的一个数值。
详见代码:
#include <cstdlib> #include <cstring> #include <cstdio> #include <iostream> #include <algorithm> using namespace std; int n, p, q, pri; /* n个球,取出p+q个球,其中黑球p个,白球q个,要求的概率最低值为p 设n个球中有k个黑球的事件为Ak ,设取出p+q个球中有p个黑球为事件B 题目所有概率为sum{p(Ak|B)}>=pri的k的取值区间 p(Ak|B)不好求解,通过贝叶斯公式p(Ak|B) = p(B|Ak)*p(Ak)/p(B)其中 p(B|Ak) = C(p, k) * C(q, n-k) / C(p+q, n); p(B) = sum( p(B|Ak) * p(Ak) ) k = 0...n; 由于有多少个黑球是等概率的,因此p(Ak)可以提出来约掉 p(Ak|B) = p(B|Ak) / sum( p(B|Ak) ); p(Ak|B) = (C(p, k) * C(q, n-k)) / sum( (C(p, t) * C(q, n-t)) ) 其中t的取值 为枚举的区间[0, n] 上式能够用来求出某个k值的概率值,由于需要枚举一个区间,那么将 这个区间的所有概率相加即可 */ const double eps = 1e-12; typedef long long LL; LL tot, seq[105]; LL c[55][55]; int sign(double x) { return x < -eps ? -1 : x > eps; } void init() { // init用来计算 c[0][0] = 1; for (int i = 1; i <= 50; ++i) { c[0][i] = 1; for (int j = 1; j <= i; ++j) { c[j][i] = c[j-1][i-1] + c[j][i-1]; } } } bool check(int a, int b) { LL x = 0; for (int i = a; i <= b; ++i) { x += c[p][i] * c[q][n-i]; } return sign(100.0 * x / tot - pri) >= 0; } void gao() { tot = 0; for (int i = 0; i <= n; ++i) { tot += c[p][i] * c[q][n-i]; } int rl, rr, len = 100; for (int i = 0; i <= n; ++i) { // 枚举区间 for (int j = i; j <= n; ++j) { if (j-i+1 >= len) continue; if (check(i, j)) { rl = i, rr = j, len = j-i+1; } } } printf("%d %d\n", rl, rr); } int main() { init(); while (scanf("%d %d %d %d", &n, &p, &q, &pri) != EOF) { gao(); } return 0; }