hdu 4465 Candy 期望+高精

题意

我们有两个盒子,盒子里分别有n个糖果,每天我们选择一个盒子去吃一个糖果,现在去吃左边盒子的糖果的概率是p。求在某天,打开盒子没有糖果,另一个盒子的糖果数的期望

分析

简单分析一下知道,肯定有一个盒子被访问 n + 1 n+1 次,设我们一共访问了 x x
我们可以这部分的期望为: C x n + 1 p n + 1 q x n 1 ( 2 n x + 1 ) C_x^{n+1}p^{n+1}q^{x-n-1}(2 * n - x + 1)

所以总期望为: x = n + 1 2 n + 1 C x n + 1 p n + 1 ( 1 p ) x n 1 ( 2 n x + 1 ) \sum_{x=n+1}^{2\cdot n+1}C_x^{n+1}p^{n+1}(1-p)^{x-n-1}(2 * n - x + 1)

式子稍微变换一下: i = 1 n + 1 C n + i i 1 p n + 1 ( 1 p ) i 1 ( n i + 1 ) \sum_{i=1}^{n+1}C_{n+i}^{i-1}p^{n+1}(1-p)^{i-1}(n-i+1)
然后我们不能确定是那个盒子里的糖果被吃完,所以有两种情况的期望,分别求出来,相加就行

eg:我们发现n有 2 e 5 2e5 故正常处理肯定爆精度了
现在有一个神奇的写法,我们对这个高精的乘法用取对数的方式变成加法,然后在取指数算回来
精度就没丢失了

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
template <typename T>
void out(T x) { cout << x << endl; }
ll fast_pow(ll a, ll b, ll p) {ll c = 1; while(b) { if(b & 1) c = c * a % p; a = a * a % p; b >>= 1;} return c;}
ll exgcd(ll a, ll b, ll &x, ll &y) { if(!b) {x = 1; y = 0; return a; } ll gcd = exgcd(b, a % b, y, x); y-= a / b * x; return gcd; }
int main()
{
    ios::sync_with_stdio(false);
    int t, td = 0;
    int n;
    double p;
    while(cin >> n >> p)
    {
        td ++;
        cout << "Case " << td << ": ";
        long double P = (n + 1) * log(p), Q = (n + 1) * log(1 - p);
        long double ans1 = n * exp(P), ans2 = n * exp(Q);
        for(int i = 1; i <= n; i ++)
        {
            P = P + log(n + i) + log(1.0 - p) - log(i);
            Q = Q + log(n + i) + log(p) - log(i);
            ans1 += exp(P + log(n - i));
            ans2 += exp(Q + log(n - i));
        }
        cout << fixed << setprecision(8) << ans1 + ans2 << endl;
    }
}

发布了76 篇原创文章 · 获赞 5 · 访问量 1301

猜你喜欢

转载自blog.csdn.net/qq_43101466/article/details/103000731