BZOJ4318 OSU!
题目描述:
osu 是一款群众喜闻乐见的休闲软件。
我们可以把osu的规则简化与改编成以下的样子:
一共有n次操作,每次操作只有成功与失败之分,成功对应1,失败对应0,n次操作对应为1个长度为n的01串。在这个串中连续的 X个1可以贡献X^3 的分数,这x个1不能被其他连续的1所包含
(也就是极长的一串1,具体见样例解释)
现在给出n,以及每个操作的成功率,请你输出期望分数,输出四舍五入后保留1位小数。
题解:
一看到概率和期望就头疼。
但仔细想一下,也许这会是你做过最水的概率DP。
我们知道:
(x+1)3
=(x+1)*(x+1)*(x+1)
=(x2+2*x+1)*(x+1)
=x3+2*x2+x+x2+2*x+1
=x3+3*x2+3*x+1;
而此处的1不再连续则增加 x3的期望。
那么我们发现每增加1期望则增加3*x2+3*x+1
我们考虑用DP来维护期望
可以看出增加的期望只与x和x2有关
所以设:x1[i]表示x的期望;x2[i]表示x2的期望。
x1[i]=(x1[i−1]+1)∗p[i];
x2[i]=(x2[i-1]+2*x1[i-1]+1)*p[i];
那么 ans[i]=ans[i-1]+(3*x2[i-1]+3*x1[i-1]+1)*p[i];
最终答案就是ans[n].
附上代码:
#include<cstdio> int n; double a[100001],x1[100001],x2[100001],ans[100001]; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%lf",&a[i]); for(int i=1;i<=n;i++) { x1[i]=(x1[i-1]+1)*a[i]; x2[i]=(x2[i-1]+2*x1[i-1]+1)*a[i]; ans[i]=ans[i-1]+(3*(x1[i-1]+x2[i-1])+1)*a[i]; } printf("%.1lf",ans[n]); }