分析:
令
f
i
f_i
fi表示前
i
i
i位的期望分数;
g
i
g_i
gi表示从第
i
i
i位往前,期望有多少的连续的'o'
每一位分为三种情况转移:
1、当前位为'x'
:
显然有:
g
i
=
0
,
f
i
=
f
i
−
1
g_i = 0,f_i = f_{i - 1}
gi=0,fi=fi−1
2、当前位为'o'
:
稍微复杂一点,为:
g
i
=
g
i
−
1
+
1
g_i = g_{i - 1} + 1
gi=gi−1+1
f
i
=
f
i
−
1
−
g
i
−
1
2
+
g
i
2
=
f
i
−
1
−
g
i
−
1
2
+
(
g
i
−
1
+
1
)
2
=
f
i
−
1
+
2
g
i
−
1
+
1
f_i = f_{i - 1} - g_{i - 1} ^ 2 +g_i ^ 2 = f_{i - 1} - g_{i - 1} ^ 2 + (g_{i - 1} + 1) ^ 2 = f_{i - 1} + 2g_{i - 1} + 1
fi=fi−1−gi−12+gi2=fi−1−gi−12+(gi−1+1)2=fi−1+2gi−1+1
3 、当前位为'?'
:
为'?'
时其实就是1、2两种情况各占
50
%
50\%
50%的可能性,把1、2两种情况相加再除以
2
2
2即可:
g
i
=
(
g
i
−
1
+
1
+
0
)
/
2
=
0.5
g
i
−
1
+
0.5
g_i = (g_{i - 1} + 1 + 0) / 2 = 0.5g_{i - 1} + 0.5
gi=(gi−1+1+0)/2=0.5gi−1+0.5
f
i
=
(
f
i
−
1
+
f
i
−
1
+
2
g
i
−
1
+
1
)
/
2
=
f
i
−
1
+
g
i
−
1
+
0.5
f_i = (f_{i - 1} + f_{i - 1} + 2g_{i - 1} + 1) / 2 = f_{i - 1} + g{i - 1} + 0.5
fi=(fi−1+fi−1+2gi−1+1)/2=fi−1+gi−1+0.5
Code:
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 3e5 + 50;
int n;
double f[maxn],g[maxn];
char c;
int main(){
cin >> n;
c = getchar();//读掉换行符
for(int i = 1; i <= n; i ++){
c = getchar();
if(c == 'o') g[i] = g[i - 1] + 1,f[i] = f[i - 1] + g[i] + g[i - 1];
else if(c == 'x') g[i] = 0,f[i] = f[i - 1];
else g[i] = (g[i - 1] + 1) / 2,f[i] = f[i - 1] + g[i - 1] + 0.5;
}
printf("%.4lf",f[n]);
return 0;
}