【洛谷1654】OSU!(期望)
- 有一个长度为\(n\)的序列,其中第\(i\)个位置有\(a_i\)的概率为\(1\)。
- 问所有极长的连续的\(1\)的长度立方和的期望。
- \(n\le10^5\)
期望
立方的期望显然不等于期望的立方,这种东西自己举几个例子就知道了。
考虑我们维护到第\(i\)个位置为止的答案为\(ans_i\),连续长度期望为\(A_i\),连续长度平方期望为\(B_i\),连续长度立方期望为\(C_i\)。
一次期望的长度转移是显然的:
\[A_i=a_i(A_{i-1}+1)
\]
对于二次期望,考虑\((x+1)^2=x^2+2x+1\),可以借助一次期望一同计算:
\[B_i=a_i(B_{i-1}+2A_{i-1}+1)
\]
知道二次期望,三次期望就同理了:
\[C_i=a_i(C_{i-1}+3B_{i-1}+3A_{i-1}+1)
\]
至于答案,由于它求的是极长连续段,所以我们有:(只有不连续了才能算答案)
\[ans_i=ans_{i-1}+(1-a_i)C_{i-1}
\]
但注意这样没有计算最后一个连续段,因此最终的答案为\(ans_n+C_n\)。
具体实现时没必要开数组。
代码:\(O(n)\)
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 100000
#define DB double
using namespace std;
int n;
int main()
{
RI i;DB x,A=0,B=0,C=0,S=0;for(scanf("%d",&n),i=1;i<=n;++i)
scanf("%lf",&x),S+=(1-x)*C,C=x*(C+3*B+3*A+1),B=x*(B+2*A+1),A=x*(A+1);//注意转移的先后顺序
return printf("%.1lf\n",S+C),0;//输出答案时要算上最后一个连续段
}
待到再迷茫时回头望,所有脚印会发出光芒