您的位置:首页 > 其它

ZOJ 3551 Bloodsucker [概率DP]

2015-11-20 17:42 381 查看
Description

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.

题意:

有N个村民,其中1个是吸血鬼,每天都有恰好两个村民互相碰面,如果碰面的是吸血鬼和正常人,则有p的概率让后者变为吸血鬼,问全部村民变成吸血鬼的期望天数。

范围:

N<=10w

解法:

很明显的概率DP,设DP[I]为I个人变成吸血鬼的期望天数,那么DP[1]=0,DP[I]=DP[I-1]+ E 其中E是在 I-1个吸血鬼,N-I+1个人中制造出一个吸血鬼的期望天数,可知每一天都有 p*(I-1)*(N-I+1)/ C(2,N)的概率制造出一个吸血鬼,记为Tp,其满足几何分布,期望为1/ Tp

代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<iostream>
#include<stdlib.h>
#include<set>
#include<map>
#include<queue>
#include<vector>
#include<bitset>
#pragma comment(linker, "/STACK:1024000000,1024000000")
template <class T>
bool scanff(T &ret){ //Faster Input
char c; int sgn; T bit=0.1;
if(c=getchar(),c==EOF) return 0;
while(c!='-'&&c!='.'&&(c<'0'||c>'9')) c=getchar();
sgn=(c=='-')?-1:1;
ret=(c=='-')?0:(c-'0');
while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
if(c==' '||c=='\n'){ ret*=sgn; return 1; }
while(c=getchar(),c>='0'&&c<='9') ret+=(c-'0')*bit,bit/=10;
ret*=sgn;
return 1;
}
#define inf 1073741823
#define llinf 4611686018427387903LL
#define PI acos(-1.0)
#define lth (th<<1)
#define rth (th<<1|1)
#define rep(i,a,b) for(int i=int(a);i<=int(b);i++)
#define drep(i,a,b) for(int i=int(a);i>=int(b);i--)
#define gson(i,root) for(int i=ptx[root];~i;i=ed[i].next)
#define tdata int testnum;scanff(testnum);for(int cas=1;cas<=testnum;cas++)
#define mem(x,val) memset(x,val,sizeof(x))
#define mkp(a,b) make_pair(a,b)
#define findx(x) lower_bound(b+1,b+1+bn,x)-b
#define pb(x) push_back(x)
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;

double dp[100100];
int main(){
tdata{
int n;
double p;
scanff(n);
scanff(p);
dp[1]=0.0;
double tot=double(n)*double(n-1)/2.0;
rep(i,2,n){
double b=double(i-1);
double a=double(n-i+1);
double tp=p*a*b/tot;
dp[i]=dp[i-1]+1/tp;
}
printf("%.3f\n",dp
);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: