某一天 WJMZBMR 在打 osu~~~ 可是他太弱逼了,有些地方彻底靠运气:(
咱们来简化一下这个游戏的规则:
有 \(n(n\le 300000)\) 次点击要作,成功了就是 o
,失败了就是 x
,分数是按 comb 计算的,连续 \(a\) 个 comb 就有 \(a^2\) 分,comb 就是极大的连续 o
。
好比 ooxxxxooooxxx
,分数就是 \(2\times 2+4\times 4=4+16=20\)。
Sevenkplus 闲的慌就看他打了一盘,有些地方跟运气无关要么是 o
要么是 x
,有些地方 o
或者 x
各有 \(50\%\) 的可能性,用 ?
号来表示。
那么 WJMZBMR 这场 osu 的指望得分是多少呢?spa
这个题若是一段一段的处理,实际上并非很好作。咱们观察到 \((x + 1) ^ 2 - x ^ 2 = 2x + 1\),那么根据指望的线性性质,咱们能够单独算每个字符的贡献。咱们设 \(dp_i\) 为考虑前 ii 个字符的指望得分,\(l_i\) 为以 \(i\) 为结尾的 comb 的指望长度,\(Comb_i\) 为第 \(i\)个字符,那么有 3 种状况:code
对于前两种状况,实际上是很是直观的,对于第三种状况,其实是求了一个平均长度。例如 ?oo
,两种状况的长度 \(l_i\) 分别为 \([0,1,2]\) 和 \([1,2,3]\) ,可是求了平均以后,长度 \(l_i\) 变成了 \([0.5,1.5,2.5]\) ,这样因为咱们的贡献是一个关于长度的一次多项式 \((2x + 1)\) ,因此长度平均以后,贡献也至关于求了一个平均,天然可以求得正确的得分指望。游戏
【AC Code】ip
const int N = 3e5 + 10; double dp[N], Comb[N]; int main() { cin.tie(nullptr)->sync_with_stdio(false); int n; string s; cin >> n >> s; for (int i = 0; i < n; ++i) { if (s[i] == 'o') { dp[i] = dp[i - 1] + Comb[i - 1] * 2 + 1; Comb[i] = Comb[i - 1] + 1; } else if (s[i] == 'x') { dp[i] = dp[i - 1]; Comb[i] = 0; } else { dp[i] = dp[i - 1] + (Comb[i - 1] * 2 + 1) / 2; Comb[i] = (Comb[i - 1] + 1) / 2; } } cout << setprecision(4) << fixed << dp[n - 1]; }
思考:若是长度为 \(a\) 的 comb 的贡献为 \(a^3\) 时该如何解决?题目连接:Hereci
Tips:因为 \((a + 1)^3 - a^3 = 3a^3 + 3a + 1\) ,因此咱们要维护 \(a^2\) 和 \(a\) 的指望,注意 \(E_{a^2} \not= E^2_a\),因此维护 \(a^2\) 的指望是必要的。get