首页 > 代码库 > codeforces 235B Let's Play Osu! 概率dp

codeforces 235B Let's Play Osu! 概率dp

题意:给定n表示有n个格子,下面每个格子为O的概率是多少。对于一段连续 x 个O的价值就是 x^2 ;求获得的价值的期望是多少。

思路:n^2=n×(n-1)+n,设ai为第i段连续O的长度,∑ai^2 = ∑[ ai+ ai*(ai-1) ] = ∑ ai*(ai-1) + ∑ai = ∑ C(ai, 2)*2 + ∑ai,那么问题可以转

化为求长度大于1的连续段数*2+O的个数的总期望。 ∑ai我们可以理解为O的总个数,所以它的期望为pi; C(ai, 2)*2我们可以认

为是连续ai个O中任意选两个点,两个点形成的段必然长度大于1,所以 ∑ C(ai, 2)*2可以理解为长度大于1的连续段数*2。我们设dp[i]

为以i结尾的连续O的段数。那么由期望公式,dp[i]=p[i]×(dp[i - 1]+1)+(1-p[i])*0=p[i]×(dp[i - 1]+1),且dp[i]-p[i]×1才表示以i结尾的长度大

于1的连续O的段数,所以ans+=2×(dp[i] - p[i]×1)。详见代码:

/*********************************************************
  file name: codeforces235B.cpp
  author : kereo
  create time:  2015年02月02日 星期一 13时02分36秒
*********************************************************/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<cmath>
#include<string>
#include<algorithm>
using namespace std;
typedef long long ll;
const int sigma_size=26;
const int N=100+50;
const int MAXN=100000+50;
const int inf=0x3fffffff;
const double eps=1e-8;
const int mod=100000000+7;
#define L(x) (x<<1)
#define R(x) (x<<1|1)
#define PII pair<int, int>
#define mk(x,y) make_pair((x),(y))
int n;
double dp[MAXN],p[MAXN];
int main(){
    while(~scanf("%d",&n)){
        double ans=0;
        for(int i=1;i<=n;i++){
            scanf("%lf",&p[i]);
            ans+=p[i];
        }
        dp[0]=0;
        for(int i=1;i<=n;i++){
            dp[i]=p[i]*(1+dp[i-1]);
            ans+=2*(dp[i]-1*p[i]);
        }
        printf("%.15f\n",ans);
    }
	return 0;
}


codeforces 235B Let's Play Osu! 概率dp