洛谷 P1654 OSU! 题解

一、题目

洛谷原题

二、思路

等了整整一年,我洛谷的用户名终于改过来了!发篇题解庆祝一下。

这道题我们需要用到期望的线性递推,具体来说是这样子的。

首先,(x1[i])表示(i)结尾(一定要注意)的连续1的期望长度。

同理,(x2[i])表示(i)结尾的连续1的期望长度的平方。

所以,有(x1[i]=(x1[i-1]+1) imes p[i] + 0 imes (1-p[i])),即(x1[i]=(x1[i-1]+1) imes p[i]).

同理,有(x2[i] = (x2[i - 1] + 2 * x1[i - 1] + 1) imes p[i]).

接下来考虑如何计算答案。

(ans[i])表示(1sim i)的期望得分。(注意:和之前的定义不同,不一定以(i)结尾!)

那么,(ans[i] = ans[i - 1] + i ext{这个点对答案的贡献})

我们又会发现,i对答案的贡献只和i之前的1有关,和i之后的无关。

如果i这一位是0,对答案没有贡献。

如果i这一位是1,则对答案有(3 imes x2[i - 1] + 3 imes x1[i - 1] + 1)的贡献。

所以(ans[i] = ans[i - 1] + (3 imes x2[i - 1] + 3 imes x1[i - 1] + 1) imes p[i])

最终答案就是(ans[n])

三、 代码

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;
#define LL long long
#define mem(s, v) memset(s, v, sizeof s)

inline LL read(void) {
	LL x = 0, f = 1; char ch = getchar();
	while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
	while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
	return f * x;
} 

const int maxn = 100005;

int n;
double p[maxn];
double x1[maxn], x2[maxn], ans[maxn];

int main() {
	cin >> n;
	for (register int i = 1; i <= n; ++i) {
		cin >> p[i];
	}
	for (register int i = 1; i <= n; ++i) {
		x1[i] = (x1[i - 1] + 1) * p[i];
		x2[i] = (x2[i - 1] + 2 * x1[i - 1] + 1) * p[i];
		ans[i] = ans[i - 1] + (3 * x2[i - 1] + 3 * x1[i - 1] + 1) * p[i];
		/*请大家思考上面这句话与 
		      ans[i] = (ans[i - 1] + 3 * x2[i - 1] + 3 * x1[i - 1] + 1) * p[i];
		的区别 
		*/
	}
	printf("%.1lf
", ans[n]);
	return 0;
}
原文地址:https://www.cnblogs.com/little-aztl/p/13758713.html