【题解】Luogu Osu!三题 期望

打开某谷,搜索osu

Luogu P1654

Luogu CF235B 

Luogu P1365

先%本机房的真·Osu!神仙 STO superminivan ORZ 

 


 

三道题都差不多,就当三倍经验了

P1365 题解

大力推式子

设$f[i]$表示以$i$结尾的期望得分,$len$为期望连续的$o$的个数

分类讨论:

①当前字母为$o$时,$f[i]=f[i-1]+((len+1)^2-len^2)$ 此时$len+1$

化简 $=>$ $f[i]=f[i-1]+2*len+1$

②当前字母为$x$时,$f[i]=f[i-1]$ 此时$len=0$ 

③当前字母为?时,为$(①+②)/2$

也就是 $f[i]=f[i-1]+len+0.5$

整理变成$f[i]=f[i-1]+(2*len+1)*p[i]$

其中$p[i]$就是i位置出现o的期望

$o$  $p[i]=1$

$x$  $p[i]=0$

$?$  $p[i]=0.5$

再看$len$怎么维护,设$x[i]$表示$i$结尾的最后一段连续$o$的个数

同样可以转化为$x[i]=(x[i-1]+1)*p[i]$

综上,转移方程为

$$f[i]=f[i-1]+(2*x[i]+1)*p[i]$$

code

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 const int mod=1e4;
 5 const int maxn=1e6+10;
 6 namespace gengyf{
 7 inline int read(){
 8     int x=0,f=1;char s=getchar();
 9     while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
10     while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
11     return f*x;
12 }
13 double f[maxn],p[maxn],x[maxn];
14 string s;int n;
15 int main(){
16     n=read();cin>>s;
17     for(int i=0;i<n;i++){
18         if(s[i]=='o')p[i+1]=1.0;
19         if(s[i]=='x')p[i+1]=0.0;
20         if(s[i]=='?')p[i+1]=0.5;
21     }
22     for(int i=1;i<=n;i++){
23         f[i]=f[i-1]+(x[i-1]*2+1.0)*p[i];
24         x[i]=(x[i-1]+1.0)*p[i];
25     }
26     printf("%.4lf",f[n]);
27     return 0;
28 }
29 /*
30  aggressive 有进取心的
31  alert 机敏的
32  alliance 联盟
33  alter 修改
34 */
35 }
36 signed main(){
37     gengyf::main();
38     return 0;
39 }
View Code

 

CF235B 

没有$?$且给出出现不同字符的概率,方程同上

code 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 const int mod=1e4;
 5 const int maxn=1e6+10;
 6 namespace gengyf{
 7 inline int read(){
 8     int x=0,f=1;char s=getchar();
 9     while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
10     while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
11     return f*x;
12 }
13 double f[maxn],p[maxn],x[maxn];
14 string s;int n;
15 int main(){
16     n=read();
17     for(int i=1;i<=n;i++){
18         scanf("%lf",&p[i]);
19         f[i]=f[i-1]+(x[i-1]*2+1.0)*p[i];
20         x[i]=(x[i-1]+1.0)*p[i];
21     }
22     printf("%.15lf",f[n]);
23     return 0;
24 }
25 /*
26  aggressive 有进取心的
27  alert 机敏的
28  alliance 联盟
29  alter 修改
30 */
31 }
32 signed main(){
33     gengyf::main();
34     return 0;
35 }
View Code

 

P1654

没有$?$,平方变成三次方

我:这还不简单,把$(len+1)^2-len^2$改成$(len+1)^3-len^3$不就行了

???怎么连样例都没过

蒟蒻眉头一皱发现事情并不简单

重新推一下式子:

$f[i]=f[i-1]+((len+1)^3-len^3)$  $=>$  $f[i]=f[i-1]+3*(len^2+len)+1$

发现化简后的式子里既有二次项也有一次项

需要分别维护

$x[i]$表示一次项的期望,$y[i]$表示二次项的期望

code

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 const int mod=1e4;
 5 const int maxn=1e6+10;
 6 namespace gengyf{
 7 inline int read(){
 8     int x=0,f=1;char s=getchar();
 9     while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
10     while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
11     return f*x;
12 }
13 double f[maxn],p[maxn],x[maxn],y[maxn];
14 string s;int n;
15 int main(){
16     n=read();
17     for(int i=1;i<=n;i++){
18         scanf("%lf",&p[i]);
19         x[i]=(x[i-1]+1.0)*p[i];
20         y[i]=(y[i-1]+2.0*x[i-1]+1)*p[i];
21         f[i]=f[i-1]+(3.0*(y[i-1]+x[i-1])+1)*p[i];
22     }
23     printf("%.1lf",f[n]);
24     return 0;
25 }
26 /*
27  aggressive 有进取心的
28  alert 机敏的
29  alliance 联盟
30  alter 修改
31 */
32 }
33 signed main(){
34     gengyf::main();
35     return 0;
36 }
View Code

 

posted @ 2019-10-29 19:24  喵の耳  阅读(164)  评论(0编辑  收藏  举报