您的位置:首页 > 其它

ZOJ 3551 —— 概率DP

2013-11-07 16:58 387 查看
                                  Bloodsucker
                                      Time Limit: 2 Seconds      Memory Limit: 65536 KB
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


Author: WU, Yingxin

Contest: ZOJ Monthly, October 2011
Submit    Status

题意是有n - 1个人和1个吸血鬼,每天都会有两个人相遇,如果一个是人一个是吸血鬼,
那么人有p的概率变成吸血鬼,问你所有人都变成吸血鬼的期望天数。
思路:有两种解法:
一、利用公式期望等于概率分之一,直接扫一遍求和即可。
       请见http://blog.chinaunix.net/uid-26372629-id-2996052.html
二、我们用dp[i]表示从i个吸血鬼到n个吸血鬼的天数期望。
       pa表示人与吸血鬼相遇的概率。C(1 , i) * C(1 , n-i) / C(2 , n)
       pp表示相遇且成功变成吸血鬼的概率。pp = pa * p
       dp[i] = (dp[i + 1] + 1) * pp + (dp[i] + 1) * (1 - pp)            这里的+1表示加了一天
       可以简化成dp[i] = (dp[i + 1] * pp + 1) / pp
       逆推一遍即可得到答案。

/*
ID: xinming2
PROG: stall4
LANG: C++
*/
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <map>
#include <string>
#include <stack>
#include <cctype>
#include <vector>
#include <queue>
#include <set>
#include <utility>
#include <cassert>
using namespace std;
///#define Online_Judge
#define outstars cout << "***********************" << endl;
#define clr(a,b) memset(a,b,sizeof(a))
#define lson l , mid  , rt << 1
#define rson mid + 1 , r , rt << 1 | 1
#define mk make_pair
#define FOR(i , x , n) for(int i = (x) ; i < (n) ; i++)
#define FORR(i , x , n) for(int i = (x) ; i <= (n) ; i++)
#define REP(i , x , n) for(int i = (x) ; i > (n) ; i--)
#define REPP(i ,x , n) for(int i = (x) ; i >= (n) ; i--)
const int MAXN = 100000 + 50;
const int sigma_size = 26;
const long long LLMAX = 0x7fffffffffffffffLL;
const long long LLMIN = 0x8000000000000000LL;
const int INF = 0x7fffffff;
const int IMIN = 0x80000000;
#define eps 1e-8
const int mod = (int)1e9 + 7;
typedef long long LL;
const LL MOD = 1000000007LL;
const double PI = acos(-1.0);

typedef pair<int , int> pi;
#define Bug(s) cout << "s = " << s << endl;
///#pragma comment(linker, "/STACK:102400000,102400000")
double dp[MAXN];
int main()
{
int n;
double p;
int T;
scanf("%d" , &T);
while(T--)
{
scanf("%d%lf" , &n , &p);
dp
= 0;
for(int i = n - 1 ; i > 0 ;i--)
{
double x , y , pp;
x = (double)i * (n - i);
y = (double)n  * (n - 1) / 2;
pp = x / y * p;
dp[i] = 1.0 * (dp[i + 1] * pp + 1) / pp;
}
printf("%.3lf\n", dp[1]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ACM 概率DP