hdu4465精度控制

这题公式不难推,就是控制精度的问题。因为公式是一些项求和,这里每一项都是接近于1的数,但是每一项里包含一个组合数和一个p^n,如果每次直接把p^n乘进去就会使数字太小,如果一直留到最后乘,可能中间就溢出了。解决的办法就是根据中间变量的大小动态地乘p^k,防止溢出,也防止数字太小丢精度

 

离比赛结束已经有一段时间了,今天再来看这题,打算把它A掉,结果查了一下解题报告,发现这题其实有不需要控制精度的方法!!!唉,当时太SB了,这种方法居然都没想到,花了一两个小时去控制精度。

其实只要在运算过程中全部取对数就可以了。。。。啊啊啊。。。

/*
 * hdu4465/win.cpp
 * Created on: 2012-11-19
 * Author    : ben
 */
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
#include <stack>
#include <string>
#include <vector>
#include <deque>
#include <list>
#include <functional>
#include <numeric>
#include <bitset>
using namespace std;
const int MAXN = 200100;
double c[MAXN], pq[MAXN], qp[MAXN];

double work(int n, double p) {
    double ret = 0;
    double logp = log(p), log1p = log(1 - p);
    c[0] = 0;
    pq[0] = (n + 1) * logp;
    qp[0] = (n + 1) * log1p;
    ret += n * exp(c[0] + pq[0]);
    ret += n * exp(c[0] + qp[0]);
    for(int k = 1; k < n; k++) {
        c[k] = c[k - 1] + log(n + k) - log(k);
        pq[k] = pq[k - 1] + log1p;
        qp[k] = qp[k - 1] + logp;
        ret += (n - k) * exp(c[k] + pq[k]);
        ret += (n - k) * exp(c[k] + qp[k]);
    }
    return ret;
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("data.in", "r", stdin);
#endif
    int t = 1, n;
    double p;
    while(scanf("%d%lf", &n, &p) == 2) {
        printf("Case %d: %.6f\n", t++, work(n, p));
    }
    return 0;
}
posted @ 2012-11-12 16:42  moonbay  阅读(...)  评论(... 编辑 收藏