某一天 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