其他分享
首页 > 其他分享> > OI loves Math(一)——期望值

OI loves Math(一)——期望值

作者:互联网

欢迎来到 OI loves Math 专栏!
本篇是第一篇。本专栏会不定期更新。谢谢大家!

期望值是什么

有一个标准的骰子(1、2、3、4、5、6),现在掷它 10000 次,问在所有出现的情况里,掷出的点数和平均是多少。

在概率论和统计学中,期望值(或数学期望、或均值,亦简称期望,物理学中称为期待值)是指在一个离散性随机变量试验中每次可能结果的概率乘以其结果的总和。
换句话说,期望值是随机试验在同样的机会下重复多次的结果计算出的等同“期望”的平均值。需要注意的是,期望值并不一定等同于常识中的“期望”——“期望值”也许与每一个结果都不相等。(换句话说,期望值是该变量输出值的平均数。期望值并不一定包含于变量的输出值集合里。)
——百度

根据定义,我们知道这个问题的答案为:

\[\sum _{i = 1} ^{10000} \sum _{j = 1} ^ {6} \frac{j}{6} = 35000 \]

很简单吧?

扩展一下

现在我们有张 $ DAG $,问从起点走到终点平均要走多少步。
比如我们有这么几条路径:

注意这里几条路径出现的概率总和应该是 1。
很显然答案为:

\[3 \times 50\% + 2 \times 20\% + 2 \times 30\% = 2.5 \]

例题

绿豆蛙的归宿(P4316)

题面

我们有张 $ DAG $,问从起点走到终点,所走的路径总长期望。

思路

对于每个点,我们统计出走到这个点的概率,分摊给多条边。
每次要遍历新的节点时,我们把答案加上概率乘上长度。
为什么要这么做呢?


对于每条边,走到它的可能性就是概率均摊后的值。
如果走到这条边,那么就是长度。
如果不走到这条边,那就是0。
根据定义,长度乘上概率。


把这个概率随身带着就可以 DFS 了。

代码

#include <bits/stdc++.h>
using namespace std;

vector<pair<int, double> > gg[100005];

double ans = 0;

void dfs(int x, double qw) {
	double ech = qw / gg[x].size();
	for (auto edg : gg[x]) {
		ans += ech * edg.second;
		dfs(edg.first, ech);
	}
}

int main() {
	int n, m;
	scanf("%d %d", &n, &m);
	for (int i = 0; i < m; i++) {
		int u, v;
		double w;
		scanf("%d %d %lf", &u, &v, &w);
		gg[u - 1].emplace_back(v - 1, w);
	}
	dfs(0, 1);
	printf("%.2lf", ans);
	return 0;
}

单选错位(P1297)

题面

Takahashi 参加 NOIP 初赛,全是选择题,全选对了。
第 $ i $ 道选择题有 $ a_i $ 项。
但是 Takahashi 抄错位了,他把第 $ i $ 道题抄在了第 $ i + 1 $ 题的位置上。
问 Takahashi 做对的题目的期望值是多少?

思路

做对肯定是相邻两道蒙对。
当 $ a_{i} = a_{i + 1} $ 时,做对的概率为 $ \frac{1}{a_{i}} = \frac{1}{a_{i + 1}} $。
当 $ a_{i} > a_{i + 1} $ 时,由于蒙在 $ [1, a_{i + 1}] $ 里的概率只有 $ \frac{a_{i + 1}}{a_{i}} $,所以做对的概率只有 $ \frac{a_{i + 1}}{a_{i}} \times \frac{1}{a_{i + 1}} = \frac{1}{a_{i}} $。
当 $ a_{i} < a_{i + 1} $ 时,由于第 $ i + 1 $ 题的答案在 $ [1, a_{i}] $ 里的概率只有 $ \frac{a_{i}}{a_{i + 1}} $,所以做对的概率只有 $ \frac{a_{i}}{a_{i + 1}} \times \frac{1}{a_{i}} = \frac{1}{a_{i + 1}} $。
综上所述,做对的概率为 $ \frac{1}{\max { a_{i}, a_{i + 1} }} $。

代码

#include <bits/stdc++.h>
using namespace std;

double a[10000005];
int n;

void init() {
	int A, B, C;
	scanf("%d %d %d %d %lf", &n, &A, &B, &C, &a[0]);
	for (int i = 1; i < n; i++) {
		a[i] = ((long long) a[i - 1] * A + B) % 100000001;
	}
	for (int i = 0; i < n; i++) {
		a[i] = (int) a[i] % C + 1;
	}
}

int main() {
	double ans = 0;
	init();
	a[n] = a[0];
	for (int i = 0; i < n; i++) {
		ans += 1 / max(a[i], a[i + 1]);
	}
	printf("%.3lf", ans);
	return 0;
}

代码都很简短,是吧?
给一个推荐吧!

标签:概率,frac,OI,int,double,期望值,loves,ans,Math
来源: https://www.cnblogs.com/AProblemSolver/p/16558742.html