题解【OSU!_BZOJ4318】(洛谷P1654)

题意

\(n\)个字符,每个字符有\(A_i\)的概率为\(1\),否则为\(0\)。这样可以构成一个\(01\)串,对于其中一个极长的连续为\(1\)的串,它能贡献的得分为这个串的长度的三次方。求最终得分。

分析一下

  • 期望型\(DP\)超级难搞的\(\cdots\),不过状态确定下来就还好啦。
  • \(F1_1\)表示以\(i\)为结尾的\(1\)串的期望长度。\(F2_i\)表示以\(i\)为结尾的\(1\)串期望长度的平方。\(F3_i\)表示以\(i\)结尾的串的得分(注意不是长度的三次方)。

\[F1_i = (F1_{i-1} +1) \cdot A_i \]

\(F_2\)的转移可以应用完全平方公式:

\[F2_i = (F2_{i-1} + 2 \cdot F1_{i-1}+1) \cdot A_i \]

\(F_3\)的转移因为要考虑第\(i\)位可能为\(0\)所以转移要考虑进去:

\[F3_i = (F3_{i-1} + 3 \cdot F2_{i - 1} + 3 \cdot F1_{i - 1} + 1) \cdot A_i + F3_{i - 1} \cdot (1 - A_i) \]

  • 然后就没啦~

代码君

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

int n;
double ar[100005], f1[100005], f2[100005], f3[100005];

int main() {
	scanf("%d", &n);
	for (int i = 1; i <= n; i++)
		scanf("%lf", &ar[i]);
	for (int i = 1; i <= n; i++) {
		f1[i] = ar[i] * (f1[i - 1] + 1);
		f2[i] = ar[i] * (f2[i - 1] + 2 * f1[i - 1] + 1);
		f3[i] = ar[i] * (f3[i - 1] + 3 * f2[i - 1] + 3 * f1[i - 1] + 1) + (1 - ar[i]) * f3[i - 1];
	}
	printf("%.1lf\n", f3[n]);
	return 0;
} \\注释加不动了...
posted @ 2018-08-13 20:25  JackHomes  阅读(184)  评论(0编辑  收藏  举报