Uva1639
题意:
有两个盒子各有n个糖果(n<=200000),每天随机选择一个:选第一个盒子的概率是p(0 ≤ p ≤ 1),第二个盒子的概率为1-p,然后吃掉其中的一颗。直到有一天,随机选择一个盒子打开一看,没糖了!现在请你计算另一个盒子里剩下的糖果数量的期望值。
解法:
我们假设到第n天的时候取得是第1个盒子的糖,此时第2个盒子有i颗糖,则在此之前打开了n+(n-i)次盒子, 其中n次打开了第一个盒子,(n-i)次打开了第二个盒子,则概率是C(2n-i,n)*p^(n+1)*(1-p)^n-i。
由于n高达20w,所以二次项系数会非常大,而后面的概率会非常小,所以如果直接计算会爆精度,所以这里我们用求对数的方法进行计算
1 #include<iostream> 2 #include<cmath> 3 using namespace std; 4 typedef long double lb; 5 const int maxn = 2e5 + 5; 6 long double logF[2 * maxn + 66]; 7 8 void generate() { 9 //预处理出n!的log值 10 logF[0] = 0; 11 for (int i = 1; i <= maxn; i++) 12 logF[i] = logF[i - 1] + log(i); 13 } 14 // C(n,m) = n!/(m!(n-m)!) 15 long double logC(int n, int m) { 16 return logF[n] - logF[m] - logF[n - m]; 17 } 18 19 int main() { 20 int n; double p; 21 generate(); 22 int kase = 1; 23 while (scanf("%d%lf", &n, &p)!=EOF) { 24 double ans = 0; 25 for (int i = 0; i <= n; i++) { 26 long double v1 = logC(2 * n - i, n) + (n + 1)*log(p) + (n - i)*log(1 - p); 27 long double v2 = logC(2 * n - i, n) + (n + 1)*log(1 - p) + (n - i)*log(p); 28 ans += (i*(exp(v1) + exp(v2))); 29 } 30 printf("Case %d: %.6lf\n", kase++, ans); 31 } 32 return 0; 33 }
原文地址:https://www.cnblogs.com/romaLzhih/p/9515177.html
时间: 2024-10-13 23:05:30