1. 程式人生 > 實用技巧 >洛谷 P1365 WJMZBMR打osu! / Easy

洛谷 P1365 WJMZBMR打osu! / Easy

洛谷 P1365 WJMZBMR打osu! / Easy

洛谷傳送門

題目背景

原 維護佇列 參見P1903

題目描述

某一天WJMZBMR在打osu~~~但是他太弱逼了,有些地方完全靠運氣:(

我們來簡化一下這個遊戲的規則

有nn次點選要做,成功了就是o,失敗了就是x,分數是按combo計算的,連續aa個combo就有a\times aa×a分,combo就是極大的連續o

比如ooxxxxooooxxx,分數就是2 \times 2 + 4 \times 4 = 4 +16=202×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(4+9)/2=6.5了

輸入格式

第一行一個整數n(n\le3\times10^5)n(n≤3×105),表示點選的個數

接下來一個字串,每個字元都是o,x,?中的一個

輸出格式

一行一個浮點數表示答案

四捨五入到小數點後44位

如果害怕精度跪建議用long double或者extended


題解:

P1654OSU!的思路基本一樣:

分類討論去求即可。

程式碼:

#include<cstdio>
using namespace std;
const int maxn=3*1e5+10;
int n;
char s[maxn];
double dp[maxn],f[maxn];
int main()
{
    scanf("%d%s",&n,s+1);
    for(int i=1;i<=n;i++)
    {
        if(s[i]=='o')
            f[i]=f[i-1]+1;
        if(s[i]=='x')
            f[i]=0;
        if(s[i]=='?')
            f[i]=(f[i-1]+1)*0.5;
    }
    for(int i=1;i<=n;i++)
    {
        if(s[i]=='o')
            dp[i]=dp[i-1]+(2*f[i-1]+1);
        if(s[i]=='x')
            dp[i]=dp[i-1];
        if(s[i]=='?')
            dp[i]=dp[i-1]+(2*f[i-1]+1)*0.5;
    }
    printf("%.4lf",dp[n]);
    return 0;
}