bzoj 4318 OSU! (概率DP)

版权声明:本人版权意识薄弱,版权声明什么的... https://blog.csdn.net/Ike940067893/article/details/88173606

题意

中文题面,难得解释了 题目传送门


分析

  • 考虑到概率 D P DP ,显然可以想到 f ( i , j ) f(i,j) 表示到第 i i 位末尾有 j j 1 1 的期望值。最后输出 f ( n + 1 , 0 ) f(n+1,0) 即可
  • n < = 100000 n<=100000
  • x x 表示连续的 1 1 的个数。所以想想怎么可以得到 x 3 x^3
  • x 3 = ( x 1 ) 3 + 3 ( x 1 ) 2 + 3 ( x 1 ) + 1 x^3=(x-1)^3+3(x-1)^2+3(x-1)+1
  • E E 表示期望,记 p [ i ] p[i] 表示第 i i 位选 1 1 的概率,则 E ( x 3 ) = (   E ( ( x 1 ) 3 ) + E ( 3 ( x 1 ) 2 ) + E ( 3 ( x 1 ) ) + E ( 1 )   ) p [ i ] E(x^3)=(\ E((x-1)^3)+E(3(x-1)^2)+E(3(x-1))+E(1)\ )*p[i]
  • 那么我们假设 f 1 f1 表示存在于末尾 x x 的期望值; f 2 f2 表示存在于末尾 x 2 x^2 的期望值; f 3 f3 表示前面的所有 x 3 x^3 的期望值,也就是答案。
  • 转移方程式就为:
    f 3 ( i ) = f 3 ( i 1 ) + ( 3 f 2 ( i 1 ) + 3 f 1 ( i 1 ) + 1 ) p [ i ] f 2 ( i ) = ( f 2 ( i 1 ) + 2 f 2 ( i 1 ) + 1 ) p [ i ] f 1 ( i ) = ( f 1 ( i 1 ) + 1 ) p [ i ] \begin{aligned}f3(i)&=f3(i-1)+(3f2(i-1)+3f1(i-1)+1)*p[i]\\ f2(i)&=(f2(i-1)+2f2(i-1)+1)*p[i]\\ f1(i)&=(f1(i-1)+1)*p[i]\end{aligned}
  • 本来第一个方程式看起来有点奇怪,其实那是合并之后的结果。我们记 L a s t Last i 1 i-1 之前的已经完结 E ( x 3 ) E(x^3) 的总和,这一部分只是为了为最终输出的答案做贡献才放在 f 3 f3 里。那么剩下的记为 N o w Now ,就是未完结、存在于末尾的 E ( x 3 ) E(x^3) 。有 L a s t + N o w = f 3 ( i 1 ) Last+Now=f3(i-1)
    • 假如这个位置选了 0 0 ,那么不会再往后做贡献,但是要把这一部分加到最终答案里面去。这一部分值为 N o w ( 1 p [ i ] ) Now*(1-p[i])
    • 否则将会对后面产生贡献,值为 N o w p [ i ] Now*p[i] ,其实也就是充当 E ( x 3 ) = (   E ( ( x 1 ) 3 ) + E ( 3 ( x 1 ) 2 ) + E ( 3 ( x 1 ) ) + E ( 1 )   ) p [ i ] E(x^3)=(\ E((x-1)^3)+E(3(x-1)^2)+E(3(x-1))+E(1)\ )*p[i] 中的 E ( ( x 1 ) 3 ) E((x-1)^3)
  • 所以 f 3 ( i ) = L a s t + N o w ( 1 p [ i ] ) + ( N o w + 3 f 2 ( i 1 ) + 3 f 1 ( i 1 ) + 1 ) p [ i ] = L a s t + N o w ( ( 1 p [ i ) ] + p [ i ] ) + ( 3 f 2 ( i 1 ) + 3 f 1 ( i 1 ) + 1 ) p [ i ] = L a s t + N o w + ( 3 f 2 ( i 1 ) + 3 f 1 ( i 1 ) + 1 ) p [ i ] = f 3 ( i 1 ) + ( 3 f 2 ( i 1 ) + 3 f 1 ( i 1 ) + 1 ) p [ i ] \begin{aligned}f3(i)&=Last+Now*(1-p[i])+(Now+3f2(i-1)+3f1(i-1)+1)*p[i]\\&=Last+Now*((1-p[i)]+p[i]) + (3f2(i-1)+3f1(i-1)+1)*p[i]\\&=Last + Now+ (3f2(i-1)+3f1(i-1)+1)*p[i]\\&=f3(i-1)+(3f2(i-1)+3f1(i-1)+1)*p[i]\end{aligned}
  • 而且 D P DP 时不用开数组
AC Code(300B)
#include <bits/stdc++.h>
using namespace std;
int main () {
	int n;
	scanf("%d", &n);
	double f1 = 0, f2 = 0, f3 = 0, p;
	while(n--) {
		scanf("%lf", &p);
		f3 += (3*f1 + 3*f2 + 1) * p;
		f2 = (f2 + 2*f1 + 1) * p;
		f1 = (f1 + 1) * p;
	}
	printf("%.1f\n", f3);
}

猜你喜欢

转载自blog.csdn.net/Ike940067893/article/details/88173606