[BZOJ] OSU!

题目

BZOJ链接......它死了。

点这里看题目。

分析

感觉是期望入门的优质题目。

首先我们需要明确:幂的期望不等于期望的幂

显然可以利用期望的线性性质将答案拆分成每一段的期望。

于是可以定义一个离散随机变量 (X_i) :前 (i) 次操作后,成功操作的极长后缀的长度

不妨设第 (i) 次操作成功的概率为 (p_i), 然后有:

[X_i= egin{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= egin{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
", ans );
	return 0;
}
原文地址:https://www.cnblogs.com/crashed/p/13396089.html