BZOJ 3450 Easy

Description

某一天WJMZBMR在打osu~~~但是他太弱逼了,有些地方完全靠運氣:(
我們來簡化一下這個遊戲的規則
有n次點擊要做,成功了就是o,失敗了就是x,分數是按comb計算的,連續a個comb就有a*a分,comb就是極大的連續o。
比如ooxxxxooooxxx,分數就是2*2+4*4=4+16=20。
Sevenkplus閒的慌就看他打了一盤,有些地方跟運氣無關要麼是o要麼是x,有些地方o或者x各有50%的可能性,用?號來表示。
比如oo?xx就是一個可能的輸入。
那麼WJMZBMR這場osu的期望得分是多少呢?
比如oo?xx的話,?是o的話就是oooxx => 9,是x的話就是ooxxx => 4
期望自然就是(4+9)/2 =6.5了

Input


第一行一個整數n,表示點擊的個數
接下來一個字符串,每個字符都是ox?中的一個

Output

一行一個浮點數表示答案
四捨五入到小數點後4位
如果害怕精度跪建議用long double或者extended

Sample Input

4
????

Sample Output

4.1250


n<=300000
osu很好玩的哦
WJMZBMR技術還行(霧),x基本上很少呢

osu是神麼,沒玩過。。

這是一個期望DP。。

用f[i]表示以i結尾的o串的長度,那麼當ch=='x' 時 p=0,ch=='o'時p=1,當ch=='?'時,p=0.5 然後f[i]=(f[i-1]+1)*p,再用一個數組g[i],表示從1到i每段o串長度平方的期望。

那麼 (x+1)^2=x^2+2*x+1,x^2對應的就是g,那麼g的轉移就是g[i]=g[i-1]+(2*f[i-1]+1)*p;

之所以乘p,是因爲g表示的前綴的答案總和,而後面兩項乘是因爲能否增加答案是概率事件。所以O(n)遞推就好了,空間複雜度O(1),滾動起來就好了。

#include <cstring>
#include <stdio.h>
double f1[2],f2;
int op;
 
 
int main(){
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        char ch=getchar();
        while(ch!='o'&&ch!='x'&&ch!='?')ch=getchar();
        double x;
        if(ch=='o')x=1.0;
        if(ch=='x')x=0;
        if(ch=='?')x=0.5;
        f1[op^1]=(f1[op]+1)*x;
        f2=f2+(2*f1[op]+1)*x;
        op^=1;
    }
    printf("%.4f\n",f2);
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章