题目大意:
有两盒糖果各有n个糖果 每天随机选取一个盒子吃掉里面的一个糖果 直到某一天打开其中一个盒子发现盒子是空的
求此时另外一盒盒子里糖果的个数的期望
分析:
最后打开的这个盒子有两种情况要么是盒子1要么是盒子2 所以最后答案应该为两个盒子的期望之和
当盒子1为空时 我们只需要枚举盒子2的糖果剩余数量 1~n
如果每天打开盒子1的概率为p 然后每一种情况的概率为 C(2*n-i , n) * pn+1 * (1-p)n-i
盒子1为空 所以盒子1选了n次 为什么是n+1次方呢 是因为最后是空的时候又选了一次 然后盒子2当然就选了 n-i 次 剩下 i 个糖果
盒子2为空时 情况也是一样
这里我们要注意一下数据的处理 由于 C(2*n-i , n) 可能会非常大 所以我们用对数来解决
然后每一种情况的概率就变成了 ln(C(2*n-i , n)) + (n+1)*ln(p) + (n-i)*ln(1-p)
然后我们要求的最红结果就是 e ln(C(2*n-i , n)) + (n+1)*ln(p) + (n-i)*ln(1-p)
AC代码:
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include<list>
#include <bitset>
#include <climits>
#include <algorithm>
#define gcd(a,b) __gcd(a,b)
#define mset(a,n) memset(a,n,sizeof(a))
#define FIN freopen("input.txt","r",stdin)
#define FOUT freopen("output.txt","w",stdout)
typedef long long LL;
const LL mod=1e9+7;
const int INF=0x3f3f3f3f;
const double PI=acos(-1.0);
using namespace std;
double logF[5000000];
double logC(int n,int m){
return logF[n]-logF[m]-logF[n-m];
}
int main (){
for (int i=1;i<=500000;i++) logF[i]=logF[i-1]+log(i);
int n;
double p;
int cc=1;
while (scanf ("%d%lf",&n,&p)!=EOF){
double ans=0;
for (int i=1;i<=n;i++){
double sum1=logC(2*n-i,n)+(n+1)*log(p)+(n-i)*log(1-p);
double sum2=logC(2*n-i,n)+(n+1)*log(1-p)+(n-i)*log(p);
ans+=(double)i*(exp(sum1)+exp(sum2));
}
printf ("Case %d: %.6lf\n",cc++,ans);
}
return 0;
}