1. 程式人生 > >ZOJ3551Bloodsucker (數學期望)

ZOJ3551Bloodsucker (數學期望)

ans post cas ould cal digits oba ostream ()

In 0th day, there are n-1 people and 1 bloodsucker. Every day, two and only two of them meet. Nothing will happen if they are of the same species, that is, a people meets a people or a bloodsucker meets a bloodsucker. Otherwise, people may be transformed into bloodsucker with probability p. Sooner or later(D

days), all people will be turned into bloodsucker. Calculate the mathematical expectation of D.

Input

The number of test cases (T, T ≤ 100) is given in the first line of the input. Each case consists of an integer n and a float number p (1 ≤ n < 100000, 0 < p ≤ 1, accurate to 3 digits after decimal point), separated by spaces.

Output

For each case, you should output the expectation(3 digits after the decimal point) in a single line.

Sample Input

1
2 1

Sample Output

1.000

題意:

開始有一個吸血鬼,n-1個平民百姓。每天一個百姓被感染的概率可求,問每個人都變成吸血鬼的天數期望。

思路:

一般期望題逆推,設dp[i]是目前已經有i個吸血鬼,所有人變成吸血鬼的期望。則dp[n]=0;答案是dp[1]。每一個dp[i]的感染概率可求是p[]=2.0*(n-i)*i/(n-1)/n*p;

則可得遞推公式: dp[i] = (dp[i+1]*p[]+1)/p[];

#include<cstdio>
#include<cstdlib>
#include<iostream>
using namespace std;
double dp[100010],p,tmp;
int main()
{
    int T,n,i;
    scanf("%d",&T);
    while(T--){
        scanf("%d%lf",&n,&p);
        dp[n]=0;
        for(i=n-1;i>=1;i--) {
            tmp=2.0*(n-i)*i/(n-1)/n*p; 
            dp[i] = (dp[i+1]*tmp+1)/tmp;  
        }
        printf("%.3lf\n",dp[1]);
    }
    return 0;
}

ZOJ3551Bloodsucker (數學期望)