BZOJ-4318 OSU!(概率dp)
题目描述
一共有 \(n(n\leq 10^5)\) 次操作,每次操作只有成功与失败之分,成功对应 \(1\),失败对应 \(0\),\(n\) 次操作对应为一个长度为 \(n\) 的 \(01\) 串。在这个串中连续的 \(x\) 个 \(1\) 可以贡献 \(x^3\) 的分数,这 \(x\) 个 \(1\) 不能被其他连续的 \(1\) 所包含(也就是极长的一串 \(1\))。
现在给出 \(n\),以及每个操作的成功率,输出期望分数(四舍五入后保留 \(1\) 位小数)。
分析
设 \(dp[i]\) 为以第 \(i\) 位为结尾的连续 \(1\) 的期望长度,则第 \(i\) 位的期望长度有 \(p[i]\) 的概率为 \(dp[i]=(dp[i-1]+1)\times p[i]\);有 \(1-p[i]\) 的概率为 \(dp[i]=0\)。
然后考虑计算每一位对答案的贡献:\(E[(x+1)^3-x^3]=E[3x^2+3x+1]=3E(x^2)+3E(x)+1\),注意此处要维护长度的平方的期望,而不是期望长度的平方,因为 长度期望的平方不等于长度平方的期望,即 \(E(x^2)\neq E(x)^2\)。再用 \(dp2[i]\) 记录以第 \(i\) 位为结尾的连续 \(1\) 的长度的平方的期望,可以借助 \(dp[i]\) 来转移,即 \(dp2[i]=(dp2[i-1]+2dp[i-1]+1)\times p[i]\)。
代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
double dp[N],dp2[N],p[N];
char s[N];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
scanf("%lf",&p[i]);
dp[0]=0;dp2[0]=0;
double ans=0;
for(int i=1;i<=n;i++)
{
dp[i]=(dp[i-1]+1)*p[i];
dp2[i]=(dp2[i-1]+2*dp[i-1]+1)*p[i];
ans=ans+(3*dp2[i-1]+3*dp[i-1]+1)*p[i];
}
printf("%.1lf\n",ans);
return 0;
}
posted on 2020-12-01 20:32 DestinHistoire 阅读(38) 评论(0) 编辑 收藏 举报