[BZOJ] OSU!
题目
BZOJ链接......它死了。
点这里看题目。
分析
感觉是期望入门的优质题目。
首先我们需要明确:幂的期望不等于期望的幂。
显然可以利用期望的线性性质将答案拆分成每一段的期望。
于是可以定义一个离散随机变量 \(X_i\) :前 \(i\) 次操作后,成功操作的极长后缀的长度。
不妨设第 \(i\) 次操作成功的概率为 \(p_i\), 然后有:
\[X_i=
\begin{cases}
X_{i-1}+1 & p_i\\
0 & 1-p_i
\end{cases}
\]
对它求一下期望:
\[E(X_i)=p_iE(X_{i-1}+1)+(1-p_i)E(0)=p_iE(X_{i-1})+p_i
\]
注意对 \(X_{i-1}\) 也需要套一个期望,因为它是随机变量,已经囊括了很多取值;而期望应该是定值。
然后考虑幂的情况。由于幂的推导之间有相似之处,这里只选取平方分析。
\[X_i^2=
\begin{cases}
(X_{i-1}+1)^2 & p_i\\
0^2 & 1-p_i
\end{cases}
\]
然后同理可以得到:
\[E(X_i^2)=p_i(E(X_{i-1}^2)+2E(X_{i-1})+1)
\]
我们再同理一下推导一下可以得到:
\[E(X_i^3)=p_i(E(X_{i-1}^3)+3E(X_{i-1}^2)+3E(X_{i-1})+1)
\]
然后就可以 \(O(n)\) 维护幂的期望。
最后考虑答案。不难发现,我们应该在一段极长的成功操作被打断之后将它加入答案。也就是说:
\[ans=\sum_{i=1}^n(1-p_{i+1})E(X_i^3)
\]
假定 \(p_{n+1}=0\) ,也就是最后一段必然会断掉。
总时间是 \(O(n)\) 。
代码
#include <cstdio>
const int MAXN = 1e5 + 5;
template<typename _T>
void read( _T &x )
{
x = 0;char s = getchar();int f = 1;
while( s > '9' || s < '0' ){if( s == '-' ) f = -1; s = getchar();}
while( s >= '0' && s <= '9' ){x = ( x << 3 ) + ( x << 1 ) + ( s - '0' ), s = getchar();}
x *= f;
}
template<typename _T>
void write( _T x )
{
if( x < 0 ){ putchar( '-' ); x = ( ~ x ) + 1; }
if( 9 < x ){ write( x / 10 ); }
putchar( x % 10 + '0' );
}
double E1[MAXN], E2[MAXN], E3[MAXN];
double p[MAXN];
int N;
int main()
{
read( N );
for( int i = 1 ; i <= N ; i ++ )
scanf( "%lf", &p[i] );
double ans = 0;
for( int i = 1 ; i <= N ; i ++ )
{
E1[i] = p[i] * ( E1[i - 1] + 1 );
E2[i] = p[i] * ( E2[i - 1] + 2 * E1[i - 1] + 1 );
E3[i] = p[i] * ( E3[i - 1] + 3 * E2[i - 1] + 3 * E1[i - 1] + 1 );
ans += E3[i] * ( 1 - p[i + 1] );
}
printf( "%.1lf\n", ans );
return 0;
}