【Uva1639】概率 + 期望 + 对数处理精度

来源:互联网 发布:安居客端口多少钱 编辑:程序博客网 时间:2024/05/23 15:28

紫书上第十章的题
【最近看数学看的想吐】

紫书上讲的很好很详细,但是那个概率表达式C(2n - i, n) * p ^ (n + 1) * (1 - p) ^ (n - i) 我看不懂
后来弄懂了意思就是:如果设最后打开盒子1,盒子2里此时还剩i颗糖。那么在最后打开盒子发现没糖了之前,一共打开了 n + (n - i) 次盒子,在盒子1里面取了n颗糖,一共有多少种方案,每种方案里,打开盒子1(加上最后那一次一共n + 1次)的概率一共是p^(n + 1),打开盒子2的概率是(1 - p) ^ (n - i),乘起来就可以了。别忘了也要考虑最后打开盒子2的情况。

因为会损失精度,所以用对数处理。
c++有好多和对数有关的函数我以前竟然不知道,超级方便啊。
因为对数运算有 log (a * b) = log a + log b; log a^n = n * log a 的这些个运算律,所以把原来乘都变成了加,除都变成了减,要注意。

#include <cstdio>#include <cmath>#include <algorithm>//#include <iostream>using namespace std;const int MAXN = 2e5 + 5;long double logC[MAXN * 2];long double C(int m, int n){    return logC[m] - logC[n] - logC[m - n];}int main(){    int n;    double p;    //logC[1] = 1;    for (int i = 1; i <= MAXN * 2; i++)    {        logC[i] = logC[i - 1] + log(i);    }    int ka = 0;    //scanf("%d", &ka);    //while ((scanf("%d %f"), &n, &p) == 2)    while (scanf("%d %lf", &n, &p) == 2)    {        ka++;        long double sum = 0.0;        for (int i = 1; i <= n; i++)        {            long double v1 = C(2 * n - i, n) + (n + 1) * log(p) + (n - i) * log(1 - p);            long double v2 = C(2 * n - i, n) + (n + 1) * log(1 - p) + (n - i) * log(p);            sum += (double)i * (exp(v1) + exp(v2));        }        printf("Case %d: %.6Lf\n", ka, sum);    }    return 0;}

我概率和期望几乎一点不会,这么一道很好写的水题我也是不大会写。慢慢来吧。前面说的都是瞎想出来的,找学数学的姐姐讲了讲但是写的时候好像都忘干净了。如果有哪里有错误希望一定告诉我qwq感谢!

原创粉丝点击