Qunju save me... (Expect DP)
Topic link: https://ac.nowcoder.com/acm/contest/17583/E
Topic source: Niuke.com
Problem Description
As we all know, Niu Kele has a very strong tongue ability.
Niu Kele wants to talk about n things, and we will number these things from 1∼n.
It takes one unit of time for Niu Kele to talk about one thing, but Niu Kele speaks things differently from ordinary people: when Niu Kele finishes talking about the i-th thing, only pi {p_i}piProbability to continue to talk about the next thing (i+1th thing), that is to say, Niu Kele has (1- pi p_ipi) probability starts from the i-1th event!
When Niu Kele finishes talking about the nth thing and decides to talk about the next thing, Niu Kele has finished talking about the nth thing.
Niu Mei is an impatient girl. She wants to ask you how long Niu Kele expects to talk about n things.
Input
The first line is an integer n
The second line is n floating point numbers, representing pi p_ipi, guarantee that p 1 p_1p1=1
Output
One floating point number per line, indicating how long Niu Kele expects to finish all the things (reserved to 3 decimal places)
Sample Input
4
1 0.6 0.4 0.2
Sample Output
38.333
Remark
For 20% of the data, 1 ≤ \le≤ n≤ \le≤ 20
for 100% of the data, 1≤ \le≤ n≤ \le≤ 1 0 5 10^5 105
Solution
This question needs to calculate the mathematical expectation, because there are actually countless situations to finish all n things, so the ordinary method of calculating the mathematical expectation is not feasible. At this time, the idea of dynamic programming is needed:
![](https://img-blog.csdnimg.cn/20200830082612437.jpg#pic_center)
设 f i f_i fiIndicates the time required to speak from the first event to the i-th event. Then the obvious answer is fn f_{n}fn。
nah fi f_ifiWhich states will be transferred?
- f i f_i fiThere are pi p_ipiThe probability of : directly from fi − 1 f_{i-1}fi−1transfer over
- f i f_ifiThere is 1 − pi 1-p_i1−piThe probability of: by fi − 1 f_{i-1}fi−1First transfer to fi − 2 f_{i-2}fi−2, and then by fi − 2 f_{i-2}fi−2back to fi f_{i}fi
∴ The state transition equation should be:
fi = pi − 1 ∗ ( fi − 1 + 1 ) + ( 1 − pi − 1 ) ∗ ( fi − 1 + 1 + fi − fi − 2 ) f_i=p_{i-1 }*(f_{i-1}+1)+(1-p_{i-1})*(f_{i-1}+1+f_i-f_{i-2})fi=pi−1∗(fi−1+1)+(1−pi−1)∗(fi−1+1+fi−fi−2)
where, fi − fi − 2 represents the time required to speak from i − 2 to i where f_i-f_{i-2} represents the time required to speak from i-2 to iAmong them ,fi−fi−2means from i−2 The time
shift required for i is simplified:fi = ( fi − 1 + 1 + ( pi − 1 − 1 ) ∗ fi − 2 ) / pi − 1 f_i=(f_{i-1} +
1+(p_{i-1}-1)*f_{i-2})/p_{i-1}fi=(fi−1+1+(pi−1−1)∗fi−2)/pi−1
Code
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=1e5+100;
int n;
double f[N],p[N];
void solve()
{
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%lf",p+i);
// 公式推导
// f[i]=p[i-1]*(f[i-1]+1)+(1-p[i-1])*(f[i-1]+1+f[i]-f[i-2])
// -> f[i]=(f[i-1]+1+(p[i-1]-1)*f[i-2])/p[i-1]
f[1]=1;
for(int i=2;i<=n;i++)
{
f[i]=(f[i-1]+1+(p[i-1]-1)*f[i-2])/p[i-1];
}
printf("%.3lf\n",f[n]);
}
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
#endif
solve();
/*
*
* ┏┓ ┏┓+ +
* ┏┛┻━━━┛┻┓ + +
* ┃ ┃
* ┃ ━ ┃ ++ + + +
* ████━████+
* ◥██◤ ◥██◤ +
* ┃ ┻ ┃
* ┃ ┃ + +
* ┗━┓ ┏━┛
* ┃ ┃ + + + +Code is far away from
* ┃ ┃ + bug with the animal protecting
* ┃ ┗━━━┓ 神兽保佑,代码无bug
* ┃ ┣┓
* ┃ ┏┛
* ┗┓┓┏━┳┓┏┛ + + + +
* ┃┫┫ ┃┫┫
* ┗┻┛ ┗┻┛+ + + +
*/
}
Finally, thank you for your study~
![](https://img-blog.csdnimg.cn/20200830095925823.png#pic_center)