题解【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;
} \\注释加不动了...