ZOJ 3551 Bloodsucker [概率DP]

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 (TT ≤ 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[n]);
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章