版權聲明:本文爲博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/M_AXSSI/article/details/52336587
4318: OSU!
Time Limit: 2 Sec Memory Limit: 128 MBSubmit: 388 Solved: 306
[Submit][Status][Discuss]
Description
osu 是一款羣衆喜聞樂見的休閒軟件。
我們可以把osu的規則簡化與改編成以下的樣子:
一共有n次操作,每次操作只有成功與失敗之分,成功對應1,失敗對應0,n次操作對應爲1個長度爲n的01串。在這個串中連續的 X個1可以貢獻X^3 的分數,這x個1不能被其他連續的1所包含(也就是極長的一串1,具體見樣例解釋)
現在給出n,以及每個操作的成功率,請你輸出期望分數,輸出四捨五入後保留1位小數。
Input
第一行有一個正整數n,表示操作個數。接下去n行每行有一個[0,1]之間的實數,表示每個操作的成功率。
Output
只有一個實數,表示答案。答案四捨五入後保留1位小數。
Sample Input
3
0.5
0.5
0.5
0.5
0.5
0.5
Sample Output
6.0
HINT
【樣例說明】
000分數爲0,001分數爲1,010分數爲1,100分數爲1,101分數爲2,110分數爲8,011分數爲8,111分數爲27,總和爲48,期望爲48/8=6.0
N<=100000
解題思路:期望與概率,終於手推出來了。首先明確每個點
的貢獻如何計算,每個點的價值是:假設當前點前面有L個一
再前面一個0,那麼它的價值就是3*L²+3*L+1,那麼我們就得出了
ans的計算公式爲對於每個點x累加(3*L²+3*L+1)*sug(x)/sug(x-L+1)*(1-p[x-L+1])
這個式子可以進行轉化,發現答案就爲1*sug(x)/sug(x-1)+6*sug(x)/sug(x-2)······
那就可以O(n)求了。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n;
long double a[100100];
int main()
{
scanf("%d",&n);
long double a1=0,a2=0;
long double sug=0; a[0]=1;
double x;
scanf("%lf",&x);
a[1]=x; a2=a[1]; sug=a[1]; a1=a[1];
for(int i=2;i<=n;++i)
{
double x;
scanf("%lf",&x); a[i]=x;
sug=sug*a[i];
a1=a1*a[i]+6*sug-a[i-1]*a[i]+a[i];
sug+=a[i];
a2+=a1;
}
printf("%.1lf",(double)a2);
}