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

洛谷 P1365 WJMZBMR打osu! / Easy

ron 題目 思路 efi spa 小數 for 背景 def

題目背景

原 維護隊列 參見P1903

題目描述

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

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

\(n\)次點擊要做,成功了就是\(`o`\),失敗了就是\(`x`\),分數是按\(combo\)計算的,連續\(a\)\(combo\)就有\(a\times a\)分,\(combo\)就是極大的連續\(`o`\)

比如\(`ooxxxxooooxxx`\),分數就是\(2 \times 2 + 4 \times 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\),表示點擊的個數

接下來一個字符串,每個字符都是\(`o`,`x`,`?`\)中的一個

輸出格式:

一行一個浮點數表示答案

四舍五入到小數點後\(4\)

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

輸入輸出樣例

輸入樣例#1:

4
????

輸出樣例#1:

4.1250

說明

\(osu\)很好玩的哦

\(WJMZBMR\)技術還行(霧),\(x\)基本上很少呢

思路:用dp數組表示期望值,用f數組表示到某位置時連續的o的個數。然後進行分類討論:
1.當\(s[i]\)\(’o’\)時,\(dp[i]=dp[i-1]+2×f[i-1]+1,f[i]=f[i-1]+1\);
因為\((x+1)^2=x^2+2 \times x + 1\)
2.當\(s[i]\)\(‘x’\)

時,\(dp[i]=dp[i-1],f[i]=0\);
3.\(else\) 期望和的平均值就好咯,因為概率都是\(0.5\),所以都乘\(0.5\)相加就可以了。

代碼:

#include<cstdio>
#include<cstring>
#define dl double
#define maxn 1000007
using namespace std;
int n;
dl dp[maxn],f[maxn];
char s[maxn];
int main() {
  scanf("%d%s",&n,s+1);
  int len=strlen(s+1);
  for(int i=1;i<=len;++i) {
    if(s[i]=='x') dp[i]=dp[i-1],f[i]=0;
    else if(s[i]=='o') dp[i]=dp[i-1]+2*f[i-1]+1,f[i]=f[i-1]+1;
    else dp[i]=dp[i-1]+f[i-1]+0.5,f[i]=(f[i-1]+1)*0.5;
  }
  printf("%0.4lf\n",dp[len]);
  return 0;
}

洛谷 P1365 WJMZBMR打osu! / Easy