X表示剩下的糖数量,如果最后打开的是p对应的盒子。划分:Xi表示剩下i个糖,最后一次选的概率为p,
前面的服从二项分布。根据全概率公式和期望的线性性,求和就好了。
精度处理要小心,n很大,组合数会很大,p的部分很小,要取对数,而且中间计算精度也要用long double才够。
组合数的对数预处理一下或者递推一下就好了。
/********************************************************* * --------------Tyrannosaurus--------- * * author AbyssalFish * **********************************************************/ #include<bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; const int maxn2 = 4e5+1; ld sum_fac_ln[maxn2]; //inline double ln_(int x) { return sum_fac_ln[x]-sum_fac_ln[x-1]; } inline ld ln_C(int m,int n) { return sum_fac_ln[m]-sum_fac_ln[n]-sum_fac_ln[m-n]; } const ld eps = 1e-11; double solve(int n, ld p) { ld q = 1-p; if(p < eps || q < eps) return n; ld E = 0; int _2n = n<<1; ld ln_p = log(p), ln_q = log(q); ld nln_p = (n+1)*ln_p; ld nln_q = (n+1)*ln_q; for(int x = 1; x <= n; x++){ ld lnC = ln_C(_2n-x,n); E += x*( exp( lnC + nln_p + (n-x)*ln_q ) + exp(lnC + nln_q + (n-x)*ln_p ) ); } return E; } //#define LOCAL int main() { #ifdef LOCAL freopen("in.txt","r",stdin); #endif for(int i = 2; i < maxn2; i++) sum_fac_ln[i] = log((ld)i); for(int i = 2; i < maxn2; i++) sum_fac_ln[i] += sum_fac_ln[i-1]; int kas = 0, n; double p; while(~scanf("%d%lf",&n,&p)){ printf("Case %d: %.6lf ", ++kas, solve(n,p)); } return 0; }