前言
原本只是想去水水的,结果发现有
3
3
3道关于
o
s
u
osu
osu的题目,于是开始走上了概率的不归路
.
.
.
...
...
总结下做概率题的方法,顺带洛谷
P
1654
P1654
P1654、
P
1365
P1365
P1365、
C
F
235
B
CF235B
CF235B的题解
方法&心得
1.
1.
1.警惕所有样例:因为遇上概率的题目一般都会有些奇奇怪怪的样例,如贿赂,听队里的
d
a
l
a
o
dalao
dalao说自己是直接跳过样例然后码
A
A
A了
2.
2.
2.多看些题目,感性理解:概率这种玄学的东西,真的用语言是很难描述的。很多题解都说的很有理,但到了出公式的时候,就有点妙了。所以我们应多练下概率的题目,找到数感
3.
3.
3.由简到繁:在洛谷的三道题尤其可见,题目给出了
x
2
x^2
x2、
x
3
x^3
x3,我们往往不是直接算,而是通过拆分,得出与更小指数的
x
x
x的关系,然后再一层层得出最终答案
4.
4.
4.好像一般不需要用到数组耶(雾:因为我们的概率只跟上一次的结果相关,所以我们没必要保存前面的结果,只需用一个变量记录就好了
题解
P1654 OSU!
分析:
题目要求的是
x
3
x^3
x3,显然直接做会很麻烦,所以我们考虑间接得到答案
假设我们当前这一位是
x
x
x,在不考虑概率的情况下,我们的下一位就变成了
x
+
1
x+1
x+1,而每次增加的都是
x
3
x^3
x3,也就是
(
x
+
1
)
3
(x+1)^3
(x+1)3,我们暴力分解下这个式子,就得到了
x
3
+
3
∗
x
2
+
3
∗
x
+
1
x^3+3*x^2+3*x+1
x3+3∗x2+3∗x+1
现在我们已经找出原式与其更小指数的关系了,然后整道题目就变得清晰了
我们可以通过记录
x
x
x和
x
2
x^2
x2,从而得到最终要增加的
x
3
x^3
x3
p
p
p代表第
i
i
i位的概率,
x
1
x_1
x1为
x
x
x的期望,
x
2
x_2
x2为
x
2
x^2
x2的期望,
a
n
s
ans
ans为最终的和
x
1
i
=
p
∗
(
x
1
i
−
1
+
1
)
x1_i=p*(x1_{i-1}+1)
x1i=p∗(x1i−1+1)
感觉这个十分显然(逃
其实就是在上一位的期望上多了一位,所以有
+
1
+1
+1,而我们要考虑第
i
i
i位的概率,所以需要
p
∗
p*
p∗
x
2
i
=
p
∗
(
x
2
i
−
1
+
2
∗
x
1
i
−
1
+
1
)
x2_i=p*(x2_{i-1}+2*x1_{i-1}+1)
x2i=p∗(x2i−1+2∗x1i−1+1)
这个式子跟我们推
x
3
x^3
x3一样,其他的跟求
x
1
x1
x1相同
a
n
s
i
=
a
n
s
i
−
1
+
p
∗
(
3
∗
x
2
i
−
1
+
3
∗
x
1
i
−
1
+
1
)
ans_i=ans_{i-1}+p*(3*x2_{i-1}+3*x1_{i-1}+1)
ansi=ansi−1+p∗(3∗x2i−1+3∗x1i−1+1)
这个式子就是我们开头所推出的式子,所以就不多说
但对于
a
n
s
i
−
1
ans_{i-1}
ansi−1为什么不用
∗
p
*p
∗p,我想了很久(可能是我太菜了),我是这么认为的,因为
a
n
s
ans
ans是一个累加的数组,我们对于以前求到的答案已经在
p
∗
(
3
∗
x
2
i
−
1
+
3
∗
x
1
i
−
1
+
1
)
p*(3*x2_{i-1}+3*x1_{i-1}+1)
p∗(3∗x2i−1+3∗x1i−1+1)时乘了,如果之后运算再乘的话…错误性显然
代码:
// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<set>
#include<queue>
#include<vector>
#include<map>
#include<list>
#include<ctime>
#include<iomanip>
#include<string>
#include<bitset>
#include<deque>
#include<set>
#define LL long long
#define mo (LL)1e11
using namespace std;
inline LL read(){
LL d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
return d*f;
}
double x,x1,x2,ans;
int main()
{
int n=read();
for(int i=1;i<=n;i++)
{
scanf("%lf",&x);
ans+=x*(3*x1+3*x2+1);
x2=x*(x2+2*x1+1);
x1=x1*x+x*1;
}
printf("%.1lf",ans);
return 0;
}
吹水
之所以现在这道紫题,是因为我觉得之后的两道题都可以以此题为铺垫搞好的理解
P1365 WJMZBMR打osu! / Easy
分析:
这道题本身与上面一题没有太大区别,可我们需要注意, t a ta ta并不是都是不确定的, t a ta ta含有一些确定的东西,所以我们需要开多一个变量,来记录连续的期望
代码:
// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<set>
#include<queue>
#include<vector>
#include<map>
#include<list>
#include<ctime>
#include<iomanip>
#include<string>
#include<bitset>
#include<deque>
#include<set>
#define LL long long
#define mo (LL)1e11
using namespace std;
inline LL read(){
LL d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
return d*f;
}
char a;
double f,g;
int main()
{
int n=read();
for(int i=1;i<=n;i++)
{
scanf("%c",&a);
if(a=='o') f+=2*g+1,g++;
else if(a=='x') g=0;
else f+=g+0.5,g=g/2+0.5;
}
printf("%.4lf",f);
return 0;
}
CF235B Let’s Play Osu!
分析
某谷良心双倍经验,跟第一题一模一样,还把 x 3 x^3 x3给扔了 . . .. ..
代码:
// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<set>
#include<queue>
#include<vector>
#include<map>
#include<list>
#include<ctime>
#include<iomanip>
#include<string>
#include<bitset>
#include<deque>
#include<set>
#define LL long long
#define mo (LL)1e11
using namespace std;
inline LL read(){
LL d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
return d*f;
}
double x,x1,x2,ans;
int main()
{
int n=read();
for(int i=1;i<=n;i++)
{
scanf("%lf",&x);
ans+=x*(2*x1+1);
x1=x1*x+x*1;
}
printf("%.15lf",ans);
return 0;
}