LuoGuP1654:OSU!
Posted chitongz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LuoGuP1654:OSU!相关的知识,希望对你有一定的参考价值。
Pre
好神奇
Solution
首先不要像我一样设\(f[i]\)表示\(i\)处为1的答案,并尝试枚举左端点,会想到\(DP\)的优化上面。
实际上考虑\(f[i]\)的来源,首先是\(a[i]\)为\(1\)的时候,难以直接转移,因为贡献是\(X^3\)。
于是可以想到(题解说):
\((X+1)^3=X^3+3\cdot X^2+3\cdot X+1\)
这样的话可以求\(a[i]=1\)时,以\(a[i]\)为右端点的\(X^2\)的期望长度和\(X\)的期望长度。
求法就玄学了。
上代码
f[i] = p[i] * (f[i - 1] + 1);//X
g[i] = p[i] * (g[i - 1] + 2 * f[i - 1] + 1);//X^2
\(f\)的转移的正确性不说了。
\(g\)的转移的正确性可以说一说。
考虑期望可以表示为所有的路径的长度的平均值(就是相同路径的出现次数之比为概率之比)。
这样的话期望\(=\fracsum(len^2)cnt\)
平方过后期望\(=\fracsum((len+1)^2)cnt\)
也就是\(=\fracsum(len^2)+2\times sum(len)+sum(1)cnt\)
这样直接展开后就可以从\(f\)转移了。
然后是状态转移
h[i] = p[i] * (h[i - 1] + 3 * g[i - 1] + 3 * f[i - 1] + 1) + (1 - p[i]) * h[i - 1];
揣摩一下就可以了。
Code
#include <cstdio>
#define ll long long
#define xx first
#define yy second
using namespace std;
const int N = 100000 + 5;
int n;
double p[N + 5], f[N + 5], g[N + 5], h[N + 5];
int main ()
#ifdef chitongz
freopen ("x.in", "r", stdin);
#endif
scanf ("%d", &n);
for (int i = 1; i <= n; ++i) scanf ("%lf", &p[i]);
for (int i = 1; i <= n; ++i)
f[i] = p[i] * (f[i - 1] + 1);
g[i] = p[i] * (g[i - 1] + 2 * f[i - 1] + 1);
h[i] = p[i] * (h[i - 1] + 3 * g[i - 1] + 3 * f[i - 1] + 1) + (1 - p[i]) * h[i - 1];
printf ("%.1lf\n", h[n]);
return 0;
Conclusion
比较有趣的构造方法。
以上是关于LuoGuP1654:OSU!的主要内容,如果未能解决你的问题,请参考以下文章