1639 (數學期望+大指數對數法)
阿新 • • 發佈:2018-12-12
題意:
兩個盒子,每個裡面都有n顆糖果,每天拿在其中一個盒子裡拿一顆糖果,概率為p和1-p,直到有一個盒子的糖全被吃完了,求另一個盒子剩餘的糖的數學期望。
思路:
利用二項式定理和基本的概率知識很容易得到結論:
第i次開啟盒子1沒糖的概率C(2n-1,n)p^(n+1)(1-p)^(n-i) 第i次開啟盒子2沒糖的概率C(2n-1,n)(1-p)^(n+1)p^(n-i)。
由於n最大有二十萬,所以直接算組合數,結果將會巨大,直接爆掉。所以這裡運用到了一個技巧就是對等式兩邊進行取對數。
得到
v1(i) = ln(C(2n-i, n)) + (n+1)ln(p) +(n-i)ln(1-p),
v2(i) = ln(C(2n-i, n)) + (n+1)ln(1-p) +(n-i)ln(p)
最終答案為 Σ{ i*(e^v1(i) +e^v2(i) ) }
這個題新學到了如何獲得取對數之後的組合數。程式碼如下
long double logfac[maxn * 2 + 1]; for (int i = 1; i <= maxn * 2; i++) logfac[i] = logfac[i - 1] + log(i); long double logc(int n, int m) { return logfac[n] - logfac[m] - logfac[n - m]; }
然後根據公式算出答案即可
#include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <queue> #include <set> #include <map> #include <stack> #include <string> #include <list> #include <cstdlib> #include <memory> #include <cstring> #include <sstream> #include <list> #include <deque> #include <bitset> #include <vector> using namespace std; #define INF 1e18 #define PI 3.141592653579 #define FRER() freopen("input.txt" , "r" , stdin); #define FREW() freopen("output.txt" , "w" , stdout); #define QIO std::ios::sync_with_stdio(false) #define mem(a, b) memset(a , b , sizeof(a)) const double eps = 1e-8; typedef long long ll; const int maxn = 200000 + 5; long double logfac[maxn * 2 + 1]; long double logc(int n, int m) { return logfac[n] - logfac[m] - logfac[n - m]; } int main() { // FRER(); // FREW(); int n; double p; int cas = 1; for (int i = 1; i <= maxn * 2; i++) logfac[i] = logfac[i - 1] + log(i); while (scanf("%d%lf", &n, &p) != EOF) { long double v1 = 0, v2 = 0; double res = 0.0; for (int i = 1; i <= n; i++) { v1 = logc(n * 2 - i, n) + (n + 1) * log(p) + (n - i) * log(1-p); v2 = logc(n * 2 - i, n) + (n + 1) * log(1 - p) + (n - i) * log(p); res += (double) i * (exp(v1) + exp(v2)); } printf("Case %d: %.6lf\n", cas++, res); } }