【期望dp】——洛谷P1654 OSU!

题目传送门:

第一眼,看不懂题意。

实际上是一道很有意思的期望dp题目。

解答参考了一下这位大大的一篇讲解:go


设a[i]表示第i个位置为1的前i位的期望长度。

容易知道:

a[i] = (a[i-1]+1) * p[i].

我们要求的是三次项,而根据期望的性质,可以用立方和公式展开,得到二次项和一次项。

设二次的a[i]表示为b[i],有b[i] = a[i]^2

b[i] = (a[i-1]+1)^2 = (a[i-1]^2) + 2*a[i-1] + 1

     = b[i-1]^2 + 2*a[i-1] + 1.

  那么也可以得到三次项,但是光求三次项没有意义,因为我们要求的是n的期望,所以只求出某位为1的情况还不够,还要算上某位为0的情况,这一情况又要由前面一位为0和为1共同得到,到了最后我们还是要求出每一位都为0的情况。

  所以改变一下思路,从一开始就求答案:

对三次项f[i]:

f[i] = (f[i-1] + 3*a[i-1] + 3*b[i-1] + 1) * p[i](第i位为1)

   + f[i-1] * (1 - p[i])           (第i位不为1)

   = f[i-1] + (3*a[i-1] + 3*b[i-1] + 1) * p[i]

最后输出答案即可!

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=1e5+10;
 4 int n;
 5 double p[N];
 6 double a[N],b[N],dp[N];
 7 int main(){
 8     scanf("%d",&n);
 9     for(int i=1;i<=n;i++){
10         scanf("%lf",&p[i]);
11     }
12     for(int i=1;i<=n;i++){
13         a[i]=(a[i-1]+1)*p[i];
14         b[i]=(b[i-1]+2*a[i-1]+1)*p[i];
15         dp[i]=dp[i-1]+(3*a[i-1]+3*b[i-1]+1)*p[i];
16     }
17     printf("%.1lf",dp[n]);
18     return 0;
19 }

所以说数学思想很重要啦! 

——抓住了时间,却不会利用的人,终究也逃不过失败的命运。
原文地址:https://www.cnblogs.com/Nelson992770019/p/11537374.html