【BZOJ3450】Easy [期望DP]
Easy
Time Limit: 10 Sec Memory Limit: 128 MB[Submit][Status][Discuss]
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
HINT
n<=300000
Main idea
连续的o提供(次数)^2的贡献,x打断连续,?等概率出现o或x,求期望。
Solution
直接期望DP即可。连续的话,下一次的贡献就是:x^2-(x-1)^2 = 2x+1。
E[i]表示到现在为止累计的期望,?的话E/2,o的话E+1,x的话清零即可。
Code
1 #include<iostream>
2 #include<string>
3 #include<algorithm>
4 #include<cstdio>
5 #include<cstring>
6 #include<cstdlib>
7 #include<cmath>
8 using namespace std;
9 typedef long long s64;
10
11 const int ONE = 300005;
12
13 int n,m;
14 char ch[ONE];
15 double Ans,E[ONE];
16
17 int get()
18 {
19 int res=1,Q=1; char c;
20 while( (c=getchar())<48 || c>57)
21 if(c=='-')Q=-1;
22 if(Q) res=c-48;
23 while((c=getchar())>=48 && c<=57)
24 res=res*10+c-48;
25 return res*Q;
26 }
27
28 int main()
29 {
30 n=get();
31 scanf("%s",ch+1);
32 for(int i=1;i<=n;i++)
33 {
34 if(ch[i] == 'o') Ans += 2.0*E[i]+1, E[i+1] = E[i] + 1;
35 if(ch[i] == '?') Ans += (2.0*E[i]+1)/2.0 , E[i+1] = (E[i]+1) / 2.0;
36 if(ch[i] == 'x') E[i+1] = 0;
37 }
38 printf("%.4lf", Ans);
39 }