前置芝士
概率初步
具体详情请参照人教版高中数学必修二课本
一个随机事件中:
-
某种可能的结果称为该实验的“样本点”
-
所有可能的结果构成的集合称为“样本空间”
在一个已知的样本空间里,随机事件就是样本空间的子集,是由若干个样本点组成的集合。
随机变量是把样本点映射成实数的函数。离散型随机变量则是取值有限或可数的随机变量。
形式化地说,一个随机变量被称为离散型随机变量,当它的值域大小 有限 或者为 可列无穷大。
概率
以下来自于 OI-Wiki
古典定义
如果一个试验满足两条:
- 试验只有有限个基本结果;
- 试验的每个基本结果出现的可能性是一样的;
这样的试验便是古典试验。
对于古典试验中的事件 \(A\),它的概率定义为 \(P(A)=\frac{m}{n}\),其中 \(n\) 表示该试验中所有可能出现的基本结果的总数目,\(m\) 表示事件 \(A\) 包含的试验基本结果数。
统计定义
如果在一定条件下,进行了 \(n\) 次试验,事件 \(A\) 发生了 \(N_A\) 次,如果随着 \(n\) 逐渐增大,频率 \(\frac{N_A}{n}\) 逐渐稳定在某一数值 \(p\) 附近,那么数值 \(p\) 称为事件 \(A\) 在该条件下发生的概率,记做 \(P(A)=p\)。
公理化定义
设 \(E\) 是随机试验,\(S\) 是它的样本空间(事件空间的同义词)。对 \(E\) 的每一个事件 \(A\) 赋予一个实数,记为 \(P(A)\),称为事件 \(A\) 的概率。这里 \(P(A)\) 是一个从集合到实数的映射,\(P(A)\) 满足以下公理:
-
非负性:对于一个事件 \(A\),有概率 \(P(A)\in [0,1]\)。
-
规范性:事件空间的概率值为 \(1\),\(P(S)=1\).
-
可加性:若 \(A\cap B=\varnothing\),则 \(P(A\cup B) = P(A)+P(B)\)。
由 \((S,P)\) 构成的这样的一个系统称为一个 概率空间。
定义
若随机变量 \(x\) 的取值有 \(x_1,x_2,\cdots,\) 一个随机事件可以表示为 \(x=x_i\) ,其概率为 \(P(x=x_i)=p_i\) ,则称 \(E(x)=\sum{p_ix_i}\) 为随机变量 \(x\) 的数学期望
也就是说,对于一个离散性随机变量 \(X\) 来说,其每个取值乘以该取值对应概率的总和成为该变量的 数学期望 是,记为 \(E(X)\)。
有
其中 \(I(X)\) 表示随机变量 \(X\) 的值域,\(S\) 表示 \(X\) 所在概率空间的样本集合。
通俗地讲,数学期望就是随机变量 \(x\) 的取值与概率的乘积之和。
性质
期望可加性
数学期望是线性函数,满足
证明:
利用乘法分配律和概率的基本乘法运算有:
这可以说是数学期望最重要的一个性质,是我们能够对数学期望进行地推求解的基本依据。
例如在掷两枚骰子的点数实验中,样本空间是由 \(36\) 个样本点组成的集合,每个样本点可以写作 \(\left(a,b\right)\) ,其中 \(1\leq a,b\leq 6\) 。
定义“掷出的点数之和”为 \(x\) ,那么随机变量 \(x\) 的取值为 \(2 \sim 12\) 。随机事件可描述为“掷出 \(x\) 点” ,即由 \(a+b = x\) 的样本点 \(\left(a,b\right)\) 构成的自己。掷出 \(8\) 点的概率 \(P(x=8)=\frac{5}{36}\) ,则掷出的点数的数学期望为
如果利用期望的可加性,
设随机变量 \(X\) 表示掷一枚骰子的点数,显然其期望值为
掷两枚骰子的点数可表示为随机变量 \(2X\) ,则有
例题
P2911 [USACO08OCT]Bovine Bones G
暴力思路
这题直接暴力模拟就能过
直接暴力模拟,没多少说的。
/*
Name: P2911 [USACO08OCT]Bovine Bones G
Solution:
By Frather_
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#define ll long long
#define InF 0x3f3f3f3f
#define kMax 10e5
#define kMin -10e5
#define kMod 998244353
using namespace std;
/*===================================================快读*/
inline int read()
{
int x = 0, f = 1;
char c = getchar();
while (c < '0' || c > '9')
{
if (c == '-')
f = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
{
x = (x << 3) + (x << 1) + (c ^ 48);
c = getchar();
}
return x * f;
}
/*===============================================定义变量*/
int s1, s2, s3;
const int _ = 1010;
struct sz
{
int num;
int id;
} t[_];
/*=============================================自定义函数*/
bool cmp(sz a, sz b)
{
return a.num == b.num ? a.id > b.id : a.num < b.num;
}
/*=================================================主函数*/
int main()
{
s1 = read();
s2 = read();
s3 = read();
for (int i = 1; i <= s1; i++)
for (int j = 1; j <= s2; j++)
for (int k = 1; k <= s3; k++)
t[i + j + k].num++;
for (int i = 1; i <= _; i++)
t[i].id = i;
sort(t + 1, t + s1 + s2 + s3 + 1, cmp);
printf("%d\n", t[s1 + s2 + s3].id);
return 0;
}
数学思路
装上脑子想一想红题能加上
的标签肯定有蹊跷。然后趁着刚装上的脑子还没过期赶紧思考数学解法。
手玩几组骰子可以发现:
对于两个骰子(面数分别是 \(a,b,\dots\))
点数之和出现次数最多的是 1+a,1+a+1,1+a+2,...,1+b 且总共有 b-a+1 个出现次数最多的和
要使出现次数最多,那么 b-a 应最大
那么对于三个甚至更多骰子情况同样如此。这样我们很容易得出 \(b\) 应取为三个数中最大的数,\(a\) 应取为三个数中最小的数,\(c\) 自然就是中间的那个数
/*
Name:
Solution:
By Frather_
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#define ll long long
#define InF 0x3f3f3f3f
#define kMax 10e5
#define kMin -10e5
#define kMod 998244353
using namespace std;
/*===================================================快读*/
inline int read()
{
int x = 0, f = 1;
char s3 = getchar();
while (s3 < '0' || s3 > '9')
{
if (s3 == '-')
f = -1;
s3 = getchar();
}
while (s3 >= '0' && s3 <= '9')
{
x = (x << 3) + (x << 1) + (s3 ^ 48);
s3 = getchar();
}
return x * f;
}
/*===============================================定义变量*/
int s1, s2, s3;
/*=============================================自定义函数*/
/*=================================================主函数*/
int main()
{
s1 = read();
s2 = read();
s3 = read();
if (s1 < s2)
swap(s1, s2);
if (s2 < s3)
swap(s2, s3);
if (s1 < s2)
swap(s1, s2);
if (s2 <= s1 - s3 + 1)
printf("%d\n", 1 + s2 + s3);
else
printf("%d\n", 2 + s1 + (s2 - s1 + s3 - 1) / 2);
return 0;
}
P4316 绿豆蛙的归宿
本题思路源于 《算法竞赛进阶指南》
设 \(F[x]\) 表示从节点 \(x\) 走到终点 \(n\) 所经过的路径的期望长度。若从 \(x\) 出发有 \(k\) 条边,分别到达 \(y_1,y_2,y_3,\dots,y_k\) ,边长分别为 \(w_1,w_2,w_3,\dots,w_k\) ,则有
显然 \(\operatorname{ans}[x]=0\) ,并且 \(\operatorname{ans}[1]\) 即为所求答案。
故可以从终点 \(n\) 出发,在反向图上进行拓扑排序,并且计算 \(\operatorname{ans}[x]\) 的值。
时间复杂度 \(O(n+m)\) 完全可以接受。
/*
Name: P4316 绿豆蛙的归宿
Solution:
By Frather_
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#define ll long long
#define InF 0x3f3f3f3f
#define kMax 10e5
#define kMin -10e5
#define kMod 998244353
using namespace std;
/*===================================================快读*/
inline int read()
{
int x=0,f=1;
char c=getchar();
while(c<'0'||c>'9')
{
if(c=='-')
f=-1;
c=getchar();
}
while(c>='0'&&c<='9')
{
x=(x<<3)+(x<<1)+(c^48);
c=getchar();
}
return x*f;
}
/*===============================================定义变量*/
int n,m;
const int _ = 1000010;
struct edge
{
int to;
int dis;
int nxt;
}e[_];
int cnt,head[_];
int in[_],out[_];
queue<int> q;
double ans[_];
/*=============================================自定义函数*/
void add(int from,int to,int dis)
{
e[++cnt].to=to;
e[cnt].dis=dis;
e[cnt].nxt=head[from];
head[from]=cnt;
}
void topa()
{
q.push(n);
while (!q.empty())
{
int u=q.front();
q.pop();
for(int i=head[u];i;i=e[i].nxt)
{
int v=e[i].to;
ans[v]+=(ans[u]+e[i].dis)/in[v];
out[v]--;
if(!out[v])
q.push(v);
}
}
}
/*=================================================主函数*/
int main()
{
n=read();
m=read();
for(int i=1;i<=m;i++)
{
int u=read();
int v=read();
int w=read();
add(v,u,w);//反向建图,便于正向对图进行反向遍历
in[u]++;
out[u]++;
}
topa();//拓扑排序
printf("%.2lf\n",ans);
return 0;
}
『题单』概率与统计
最后
鸣谢:
预计过几天会有关于数学期望更深入的笔记叭
完结。