「LG1365」WJMZBMR打osu! / Easy

Description

某一天WJMZBMR在打osu但是他太弱逼了,有些地方完全靠运气:(
我们来简化一下这个游戏的规则
nn次点击要做,成功了就是o,失败了就是x,分数是按combo计算的,连续aa个combo就有a×aa\times a分,combo就是极大的连续o
比如ooxxxxooooxxx,分数就是2×2+4×4=4+16=202 \times 2 + 4 \times 4 = 4 +16=20
Sevenkplus闲的慌就看他打了一盘,有些地方跟运气无关要么是o要么是x,有些地方o或者x各有50%的可能性,用?号来表示。
比如oo?xx就是一个可能的输入。
那么WJMZBMR这场osu的期望得分是多少呢?
比如oo?xx的话,?o的话就是oooxx \ge 9,是x的话就是ooxxx \ge 4
期望自然就是(4+9)/2=6.5(4+9)/2 =6.5

Input

第一行一个整数nn,表示点击的个数

接下来一个字符串,每个字符都是o,x,?中的一个

Output

一行一个浮点数表示答案
四舍五入到小数点后44位

Sample Input

1
2
4
????

Sample Output

1
4.1250

HINT

0n3000000\leq n\leq 300000

Solution

force

fi,0f_{i,0}fi,1f_{i,1}表示第ii位,是否正确的的期望价值。
枚举从jj转移过来。复杂度是O(n2)O(n^2)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<map>
#include<queue>
#include<bitset>
#define mk make_pair
#define fi first
#define nd second
#define pii pair<int,int>
#define pb push_back
#define sqr(x) ((x)*(x))
using namespace std;
typedef long long ll;
inline ll read() {ll x = 0; char ch = getchar(), w = 1;while(ch < '0' || ch > '9') {if(ch == '-') w = -1;
ch = getchar();}while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0';ch = getchar();}return x * w;}
void write(ll x) {if(x < 0) putchar('-'), x = -x;if(x > 9) write(x / 10);putchar(x % 10 + '0');}
inline void writeln(ll x) {write(x);puts("");}
const int N = 310000;
double f[N][2];
int n;
double a[N];
char s[N];
int main() {
n = read();
scanf("%s", s+1);
for(int i = 1; i <= n; ++i) if(s[i] == 'o') a[i] = 1;
else if(s[i] == '?') a[i] = 0.5;
f[0][0] = 0;
for(int i = 1; i <= n; ++i) {
f[i][0] = (f[i - 1][0] + f[i - 1][1]) * (1 - a[i]);
double t = 1;
for(int j = 1; j <= i; ++j) {
t *= a[i - j + 1];
f[i][1] += (f[i - j][0] + j * j * (1 - a[i - j])) * t;
}
}
printf("%.4f\n",f[n][0] + f[n][1]);
return 0;
}

std

gig_i表示到第ii位的期望长度。
fif_i表示到第ii位的期望价值。
gig_ixjb转移一下。fif_i也xjb转移一下。
(x+1)2=x2+2x+1(x+1)^2=x^2 + 2x+1
根据期望线性性,fi=fi1+(2gi1+1)aif_i=f_{i-1}+(2g_{i-1}+1)\cdot a_i
gi=0(1pi)+(gi1+1)pig_i=0\cdot (1-p_i)+(g_{i-1}+1)\cdot p_i
搞完了~

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<map>
#include<queue>
#include<bitset>
#define mk make_pair
#define fi first
#define nd second
#define pii pair<int,int>
#define pb push_back
#define sqr(x) ((x)*(x))
using namespace std;
typedef long long ll;
inline ll read() {ll x = 0; char ch = getchar(), w = 1;while(ch < '0' || ch > '9') {if(ch == '-') w = -1;
ch = getchar();}while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0';ch = getchar();}return x * w;}
void write(ll x) {if(x < 0) putchar('-'), x = -x;if(x > 9) write(x / 10);putchar(x % 10 + '0');}
inline void writeln(ll x) {write(x);puts("");}
const int N = 310000;
double f[N], g[N];
int n;
double a[N];
char s[N];
int main() {
n = read();
scanf("%s", s+1);
for(int i = 1; i <= n; ++i) if(s[i] == 'o') a[i] = 1;
else if(s[i] == '?') a[i] = 0.5;
for(int i = 1; i <= n; ++i) {
g[i] = (g[i - 1] + 1) * a[i];
//f[i] = f[i - 1] + g[i - 1] * g[i - 1] + 2 * g[i - 1] +1;
f[i] = f[i - 1] + (2 * g[i - 1] +1) * a[i];
}
printf("%.4f\n",f[n]);
return 0;
}