Easy与Osu

Easy

题目描述

某一天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了

输入

第一行一个整数n,表示点击的个数
接下来一个字符串,每个字符都是ox?中的一个

输出

一行一个浮点数表示答案
四舍五入到小数点后4位
如果害怕精度跪建议用long double或者extended

样例输入

4
????

样例输出

4.1250


n<=300000
osu很好玩的哦
WJMZBMR技术还行(雾),x基本上很少呢


Osu

题目描述

osu 是一款群众喜闻乐见的休闲软件。 
我们可以把osu的规则简化与改编成以下的样子: 
一共有n次操作,每次操作只有成功与失败之分,成功对应1,失败对应0,n次操作对应为1个长度为n的01串。在这个串中连续的 X个1可以贡献X^3 的分数,这x个1不能被其他连续的1所包含(也就是极长的一串1,具体见样例解释) 
现在给出n,以及每个操作的成功率,请你输出期望分数,输出四舍五入后保留1位小数。 

输入

第一行有一个正整数n,表示操作个数。接下去n行每行有一个[0,1]之间的实数,表示每个操作的成功率。 

输出

只有一个实数,表示答案。答案四舍五入后保留1位小数。 
 

样例输入

3 
0.5 
0.5 
0.5 

样例输出

6.0 

【题解】
一个游戏产生的两道题,只不过一个是二次方一个是三次方,套路非常相近。f[i]表示以i为结尾的极大连续1长度的期望(其实在此处还不用考虑结尾不结尾的事),g[i]表示平方的期望,h[i]表示立方的期望。g[i]本应=(f[i-1]+1)^2=f[i-1]*f[i-1]+2*f[i-1]+1,但是这里平方是在期望意义下的,所以用g[i-1]代替f[i-1]*f[i-1],最后乘上这一位是1的概率,立方同理。计算结果时要考虑下一位的情况了,再乘上(1-p[i+1])。这道题在期望、概率、数字之间的转化比较灵活,也展现了高次递推的一些套路。安心地使用double并没有炸精度。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int sj=300010;
int n;
double f[sj],g[sj],jg;
char a[sj];
int main()
{
    //freopen("t.txt","r",stdin);
    scanf("%d%s",&n,a);
    for(int i=1;i<=n;i++)
    {
       if(a[i-1]=='o')  
       {
         f[i]=f[i-1]+1;
         g[i]=g[i-1]+2*f[i-1]+1;
       }
       if(a[i-1]=='x')
       {  
         f[i]=0;
         g[i]=0;
       }
       if(a[i-1]=='?')
       {  
         f[i]=(f[i-1]+1)/2;
         g[i]=(g[i-1]+2*f[i-1]+1)/2;
       }
       if(a[i]!='?'&&a[i]!='o')  jg+=g[i];
       if(a[i]=='?')  jg+=g[i]/2;
    }
    printf("%.4lf",jg);
    //while(1);
    return 0;
}

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int sj=100010;
double f[sj],g[sj],h[sj],jg,p[sj];
int n;
int main()
{
    //freopen("t.txt","r",stdin);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)  
    {
      scanf("%lf",&p[i]);
      f[i]=(f[i-1]+1)*p[i];
    }
    for(int i=1;i<=n;i++) g[i]=(g[i-1]+2*f[i-1]+1)*p[i];
    for(int i=1;i<=n;i++)
    { 
      h[i]=(h[i-1]+3*g[i-1]+3*f[i-1]+1)*p[i];
      jg+=h[i]*(1-p[i+1]);
    }
    printf("%.1lf",jg);
    //while(1);
    return 0;
}
 
原文地址:https://www.cnblogs.com/moyiii-/p/7241936.html