天天看點

CF 235B Let's Play Osu!(機率dp)

Description

You're playing a game called Osu! Here's a simplified version of it. There are n clicks in a game. For each click there are two outcomes: correct or bad. Let us denote correct as "O", bad as "X", then the whole play can be encoded as a sequence of n characters "O" and "X".

Using the play sequence you can calculate the score for the play as follows: for every maximal consecutive "O"s block, add the square of its length (the number of characters "O") to the score. For example, if your play can be encoded as "OOXOOOXXOO", then there's three maximal consecutive "O"s block "OO", "OOO", "OO", so your score will be 22 + 32 + 22 = 17. If there are no correct clicks in a play then the score for the play equals to 0.

You know that the probability to click the i-th (1 ≤ i ≤ n) click correctly is pi. In other words, the i-th character in the play sequence has pi probability to be "O", 1 - pi to be "X". You task is to calculate the expected score for your play.

input

The first line contains an integer n (1 ≤ n ≤ 105) — the number of clicks. The second line contains n space-separated real numbers p1, p2, ..., pn (0 ≤ pi ≤ 1).

There will be at most six digits after the decimal point in the given pi.

output

Print a single real number — the expected score for your play. Your answer will be considered correct if its absolute or relative error does not exceed 10 - 6.

這個題網上的大神都說是n^2=2*C(2,n)+n;然後就可以推DP了

但是對于完全看不懂也想不通網上大神的題解的本渣來說,這個方法明顯不适用我

是以我還是用最蠢的方法來推

這個題既然考機率DP,那麼相鄰兩個狀态之間一定有某種規律可循

于是我們可以分别推出隻有兩個按鈕,三個按鈕,四個按鈕時的期望公式

可以得到:

兩個:2*p1*p2+p1+p2

三個:2*p1*p2*p3+2*p2*p3+2*p1*p2+p1+p2+p3

四個:2*p1*p2*p3*p4+2*p1*p2*p3+2*p2*p3*p4+2*p1*p2+2*p2*p3+2*p3*p4+p1+p2+p3+p4

設第n個的期望為dp[n],則以上三組式子反映出一個規律

即:

dp[i]=(dp[i-1]-dp[i-2])*p[i]+dp[i-1]+p[i]+p[i]*p[i-1];

然後這個題就解決了

代碼:

#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
#include<sstream>
#include<algorithm>
#include<utility>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<math.h>
#include<iterator>
#include<stack>
using namespace std;
typedef __int64 LL;
typedef unsigned long long ULL;
const double eps=1e-8,PI=3.1415926538;
const LL MOD=1000000000+7;
const LL MAXN=100000+7;
double p[MAXN],dp[MAXN];
int n;
int main()
{
    while(scanf("%d",&n)!=-1)
    {
        dp[0]=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%lf",&p[i]);
            dp[i]=0;
        }
        dp[1]=p[1];
        for(int i=2;i<=n;i++)
        {
            dp[i]=(dp[i-1]-dp[i-2])*p[i]+dp[i-1]+p[i]+p[i]*p[i-1];
        }
        printf("%.15f\n",dp[n]);
    }
}
           
CF 235B Let's Play Osu!(機率dp)