BZOJ 3450 - Tyvj1952 Easy
Published on 2016-11-28描述
某一天 WJMZBMR 在打 osu~~~ 但是他太弱逼了,有些地方完全靠运气:(
我们来简化一下这个游戏的规则:
有 次点击要做,成功了就是 o
,失败了就是 x
,分数是按 comb 计算的,连续 个 comb 就有 分,comb 就是极大的连续 o
。
比如 ooxxxxooooxxx
,分数就是 。
Sevenkplus 闲的慌就看他打了一盘,有些地方跟运气无关要么是 o
要么是 x
,有些地方 o
或者 x
各有 的可能性,用 ?
号来表示。
那么 WJMZBMR 这场 osu 的期望得分是多少呢?
分析
这个题如果一段一段的处理,实际上并不是很好做。我们观察到 ,那么根据期望的线性性质,我们可以单独算每一个字符的贡献。我们设 为考虑前 个字符的期望得分, 为以 为结尾的 comb 的期望长度, 为第 个字符,那么有 3 种情况:
- ,则 ,。
- ,则 ,。
- ,则 ,。
对于前两种情况,其实是非常直观的,对于第三种情况,实际上是求了一个平均长度。例如 ?oo
,两种情况的长度 分别是 和 ,但是求了平均之后,长度 变成了 ,这样由于我们的贡献是一个关于长度的一次多项式(),所以长度平均之后,贡献也相当于求了一个平均,自然能够求得正确的得分期望。
思考:如果长度为 的 comb 的贡献为 ,怎么做呢?
提示:由于 ,所以我们需要维护 和 的期望,注意 ,所以维护 的期望是必要的。这个题是:BZOJ 4318
代码
// Created by Sengxian on 2016/11/28. // Copyright (c) 2016年 Sengxian. All rights reserved. // BZOJ 3450 期望 DP #include <bits/stdc++.h> using namespace std; const int MAX_N = 300000 + 3; char str[MAX_N]; double dp[MAX_N], len[MAX_N]; int n; int main() { scanf("%d%s", &n, str); for (int i = 0; i < n; ++i) if (str[i] == 'o') { dp[i] = dp[i - 1] + len[i - 1] * 2 + 1; len[i] = len[i - 1] + 1; } else if (str[i] == 'x') { dp[i] = dp[i - 1]; len[i] = 0; } else { dp[i] = dp[i - 1] + (len[i - 1] * 2 + 1) / 2; len[i] = (len[i - 1] + 1) / 2; } printf("%.4f\n", dp[n - 1]); return 0; }