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基本上很少呢
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);
}