[BZOJ3450/TYVJ1952]Easy

Description
某一天WJMZBMR在打osu(simsimsim)但是他太弱逼了,有些地方完全靠运气:(
我们来简化一下这个游戏的规则
有n次点击要做,成功了就是o,失败了就是x,分数是按comb计算的,连续a个comb就有aa分,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
osu很好玩的哦
WJMZBMR技术还行(雾),x基本上很少呢


考虑dp,我们设f[i]表示到第i个点的得分期望,g[i]表示到第i个点o的长度期望,转移就十分显然了

((x+1)^2=x^2+2x+1)

/*program from Wolfycz*/
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 0x7f7f7f7f
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline char gc(){
	static char buf[1000000],*p1=buf,*p2=buf;
	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
inline int frd(){
	int x=0,f=1; char ch=gc();
	for (;ch<'0'||ch>'9';ch=gc())	if (ch=='-')	f=-1;
	for (;ch>='0'&&ch<='9';ch=gc())	x=(x<<3)+(x<<1)+ch-'0';
	return x*f;
}
inline int read(){
	int x=0,f=1; char ch=getchar();
	for (;ch<'0'||ch>'9';ch=getchar())	if (ch=='-')	f=-1;
	for (;ch>='0'&&ch<='9';ch=getchar())	x=(x<<3)+(x<<1)+ch-'0';
	return x*f;
}
inline void print(int x){
	if (x<0)	putchar('-'),x=-x;
	if (x>9)	print(x/10);
	putchar(x%10+'0');
}
const int N=3e5;
double f[N+10],g[N+10];
char s[N+10];
int main(){
	int n=read();
	scanf("%s",s+1);
	for (int i=1;i<=n;i++){
		if (s[i]=='x')	f[i]=f[i-1],g[i]=0;
		if (s[i]=='o')	f[i]=f[i-1]+2*g[i-1]+1,g[i]=g[i-1]+1;
		if (s[i]=='?')	f[i]=f[i-1]+g[i-1]+0.5,g[i]=(g[i-1]+1)/2;
	}
	printf("%.4lf
",f[n]);
	return 0;
}
原文地址:https://www.cnblogs.com/Wolfycz/p/10004050.html