首页 > 其他 > 详细

期望练习

时间:2021-05-20 00:19:12      阅读:29      评论:0      收藏:0      [点我收藏+]

概率与期望

前言

做到的与期望相关的题目都会放到这里 目前是照着一个题单再刷 如果是期望 \(dp\) 会同步放到这里

概率题都不是好东西

题目

1. \(CF865C\ Gotta\ Go\ Fast\)

我永远想不明白的期望题

二分一个期望通过时间 期望 \(dp\) 进行检验

状态 \(f_{i, j}\) 表示剩余 \(i\) 个关卡 剩余 \(j\) 的时间时期望通关的时间

转移 \(f_{i, j} = (f_{i + 1, j + a_i} + a_i) \times p_i / 100 + (f_{i + 1, j + b_i} + b_i) \times (100 - p_i) / 100\)

由于可以重来 对二分出的值取 \(\min\)

转移 \(f_{i, j} = \min\{mid, (f_{i + 1, j + a_i} + a_i) \times p_i / 100 + (f_{i + 1, j + b_i} + b_i) \times (100 - p_i) / 100\}\)

爆零小技巧

技术分享图片

/*
  Time: 5.15
  Worker: Blank_space
  Source: CF865C Gotta Go Fast
*/
/*--------------------------------------------*/
#include<cstdio>
#include<algorithm>
/*--------------------------------------头文件*/
const int A = 1e4 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
/*------------------------------------常量定义*/
int n, m, a[60], b[60], p[60];
double f[60][5010];
/*------------------------------------变量定义*/
inline int read() {
	int x = 0, f = 1; char ch = getchar();
	while(ch < ‘0‘ || ch > ‘9‘) {if(ch == ‘-‘) f = -1; ch = getchar();}
	while(ch >= ‘0‘ && ch <= ‘9‘) {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
	return x * f;
}
/*----------------------------------------快读*/
bool check(double x) {
	for(int i = n - 1; ~i; i--)
	{
		for(int j = m + 1; j < 5000; j++) f[i + 1][j] = x;
		for(int j = 0; j <= m; j++)
			f[i][j] = std::min(x, (f[i + 1][j + a[i]] + a[i]) * p[i] * 1.0 / 100 + (f[i + 1][j + b[i]] + b[i]) * (100 - p[i]) * 1.0 / 100);
	}
	return f[0][0] < x;
}
/*----------------------------------------函数*/
int main() {
	n = read(); m = read();
	for(int i = 0; i < n; i++) a[i] = read(), b[i] = read(), p[i] = read();
	double l = 0, r = 1e10, mid = (l + r) / 2;
	for(int i = 1; i <= 100; i++, mid = (l + r) / 2)
		if(check(mid)) r = mid; else l = mid;
	printf("%.10lf", l);
	return 0;
}

2. \(P4550\) 收集邮票

第一个认真 推的期望题

\(k\) 次需要支付 \(k\) 元钱 若一共购买了 \(x\) 次 则需要 \(\sum_{i = 1}^x i = \frac{x^2 + x}2\)

状态 \(g_i\) 表示已经买到了 \(i\) 种时 买全所有的还需要的期望次数 相应的 \(f_i\) 表示对应的二次方

转移 \(g_i = (g_i + 1)\frac in + (g_{i + 1} + 1)\frac {n - i}n\)

发现这个转移构成了环 将 \(g_i\) 弄到另一边 化简 得

\[g_i = \frac n{n - i} + g_{i + 1} \]

相应的 有 \(f_i = (f_i + 2g_i + 1)\frac in + (f_{i + 1} + 2g_{i + 1} + 1)\frac {n - i}n\)

化简 得:

\[f_i = \frac n{n - i} + \frac{2ig_i}{n - i} + 2g_{i + 1} + f_{i + 1} \]

代码

/*
  Time: 5.15
  Worker: Blank_space
  Source: P4550 收集邮票
*/
/*--------------------------------------------*/
#include<cstdio>
/*--------------------------------------头文件*/
const int A = 1e4 + 7;
/*------------------------------------常量定义*/
int n;
double g[A], f[A];
/*------------------------------------变量定义*/
inline int read() {
	int x = 0, f = 1; char ch = getchar();
	while(ch < ‘0‘ || ch > ‘9‘) {if(ch == ‘-‘) f = -1; ch = getchar();}
	while(ch >= ‘0‘ && ch <= ‘9‘) {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
	return x * f;
}
/*----------------------------------------快读*/

/*----------------------------------------函数*/
int main() {
	n = read();
	for(int i = n - 1; ~i; i--)
		g[i] = 1.0 * n / (n - i) + g[i + 1], f[i] = 1.0 * n / (n - i) + 2.0 * i * g[i] / (n - i) + 2 * g[i + 1] + f[i + 1];
	printf("%.2lf", (g[0] + f[0]) / 2);
	return 0;
}

3. \(P3802\) 小魔女帕琪

期望 \(dp\)

我发现这种题就是式子化一张纸 代码一两行 遇到直接推式子...

\(n = \sum_{i = 1}^7 a_i\)

考虑前七次触发的概率 为

\[\frac {a_1}{n} \times \frac {a_2}{n - 1}\times \frac {a_3}{n - 2}\times \frac {a_4}{n - 3}\times \frac {a_5}{n - 4}\times \frac {a_6}{n - 5}\times \frac {a_7}{n - 6} = \prod_{i = 1}^7 \frac {a_i}{n - i + 1} \]

由于 \(a_i\) 的顺序 前面在乘上一个 \(7!\)

所以前七次能够触发的概率 设为 \(p_1\)

\[p_1 = 7! \times \prod_{i = 1}^7 \frac {a_i}{n - i + 1} \]

考虑第八个继续触发的概率 其与第一个无关 若第一个随机到的为 \(a_1\) 那么有:

\[\frac {a_1}n \times \frac {a_1 - 1}{n - 1} \times \frac {a_2}{n - 2}\times \frac {a_3}{n - 3}\times \frac {a_4}{n - 4}\times \frac {a_5}{n - 5}\times \frac {a_6}{n - 6}\times \frac {a_7}{n - 7} = \frac{a_1 - 1}{n}\prod_{i = 1}^7 \frac{a_i}{n - i} \]

第一个是随机的 所以概率 设为 \(p_2\) 为 :

\[\begin{array} \p_2 & = 7! \times \left( \frac{a_1 - 1}{n}\prod_{i = 1}^7 \frac{a_i}{n - i} + \frac{a_2 - 1}{n}\prod_{i = 1}^7 \frac{a_i}{n - i} + \frac{a_3 - 1}{n}\prod_{i = 1}^7 \frac{a_i}{n - i} + \frac{a_4 - 1}{n}\prod_{i = 1}^7 \frac{a_i}{n - i} + \frac{a_5 - 1}{n}\prod_{i = 1}^7 \frac{a_i}{n - i} + \frac{a_6 - 1}{n}\prod_{i = 1}^7 \frac{a_i}{n - i} + \frac{a_7 - 1}{n}\prod_{i = 1}^7 \frac{a_i}{n - i}\right)\& = 7! \times \frac{\sum_{i = 1}^7a_i - 7}{n} \times \prod_{i = 1}^7 \frac{a_i}{n - i}\& = 7! \times \frac{n - 7}{n} \times \prod_{i = 1}^7 \frac{a_i}{n - i}\& = 7! \times \frac{n - 7}{n} \times \frac {a_1}{n - 1} \times \frac {a_2}{n - 2}\times \frac {a_3}{n - 3}\times \frac {a_4}{n - 4}\times \frac {a_5}{n - 5}\times \frac {a_6}{n - 6}\times \frac {a_7}{n - 7}\& = 7! \times \prod_{i = 1}^7 \frac {a_i}{n - i + 1} \end{array} \]

我们发现了什么

\[p_1 = p_2 \]

这就好办了...

下面就不赘述了

代码

/*
  Time: 5.15
  Worker: Blank_space
  Source: P3802 小魔女帕琪
*/
/*--------------------------------------------*/
#include<cstdio>
/*--------------------------------------头文件*/
int a[8], sum;
double ans = 1;
/*------------------------------------变量定义*/
inline int read() {
	int x = 0, f = 1; char ch = getchar();
	while(ch < ‘0‘ || ch > ‘9‘) {if(ch == ‘-‘) f = -1; ch = getchar();}
	while(ch >= ‘0‘ && ch <= ‘9‘) {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
	return x * f;
}
/*----------------------------------------快读*/

/*----------------------------------------函数*/
int main() {
	for(int i = 1; i <= 7; i++) a[i] = read(), sum += a[i];
	for(int i = 1; i <= 6; i++) ans *= a[i] * 1.0 / (sum + 1 - i) * i;
	printf("%.3lf", ans * a[7] * 7.0);
	return 0;
}

4. \(P5104\) 红包发红包

过于数学的证明方法我不会 只能感性理解

第一个人可能抢到的钱的区间为 \([0, w]\) 概率是均等的

也就是抢到每一个金额的概率都是 \(\frac 1{w + 1}\)

所以期望为

\[\begin{array}\E & = \sum_{i = 0}^w \frac 1{w + 1} \times i\& = \frac{w\left(w + 1\right)}{2(w + 1)}\& = \frac w2 \end{array} \]

对于第二个人 剩余的钱就是 \(\frac w2\) 期望为 \(\frac w{2^2}\)

同理 第 \(k\) 个人获得的钱的期望为 \(\frac w{2^k}\)

/*
  Time: 5.19
  Worker: Blank_space
  Source: P5104 红包发红包
*/
/*--------------------------------------------*/
#include<cstdio>
#define int long long
/*--------------------------------------头文件*/
const int mod = 1e9 + 7;
/*------------------------------------常量定义*/
int w, k;
/*------------------------------------变量定义*/
inline int read() {
	int x = 0, f = 1; char ch = getchar();
	while(ch < ‘0‘ || ch > ‘9‘) {if(ch == ‘-‘) f = -1; ch = getchar();}
	while(ch >= ‘0‘ && ch <= ‘9‘) {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
	return x * f;
}
/*----------------------------------------快读*/
int power(int a, int b, int res = 1) {for(; b; b >>= 1, a = a * a % mod) if(b & 1) res = res * a % mod; return res;}
/*----------------------------------------函数*/
signed main() {
	w = read(); read(); k = read(); printf("%lld", w * power(power(2, k), mod - 2) % mod);
	return 0;
}

5. \(P6154\) 游走

结论: 有向无环图中路径长度的期望 \(\frac {len}{cnt}\)

怎么出来的 不知道 题解里都是这么说的

/*
  Time: 5.19
  Worker: Blank_space
  Source: P6154 游走
*/
/*--------------------------------------------*/
#include<cstdio>
#define int long long
/*--------------------------------------头文件*/
const int A = 1e4 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod = 998244353;
const int INF = 0x3f3f3f3f;
/*------------------------------------常量定义*/
int n, m, f[B << 1], g[B << 1], sum1, sum2;
struct edge {int v, nxt;} e[C << 1];
int head[B << 1], ecnt;
/*------------------------------------变量定义*/
inline int read() {
	int x = 0, f = 1; char ch = getchar();
	while(ch < ‘0‘ || ch > ‘9‘) {if(ch == ‘-‘) f = -1; ch = getchar();}
	while(ch >= ‘0‘ && ch <= ‘9‘) {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
	return x * f;
}
/*----------------------------------------快读*/
void add_edge(int u, int v) {e[++ecnt] = (edge){v, head[u]}; head[u] = ecnt;}
void dfs(int u) {
	if(g[u]) return ; g[u] = 1;
	for(int i = head[u], v = e[i].v; i; i = e[i].nxt, v = e[i].v)
		dfs(v), g[u] = (g[u] + g[v]) % mod, f[u] = (f[u] + f[v] + g[v]) % mod;
	sum1 = (sum1 + f[u]) % mod; sum2 = (sum2 + g[u]) % mod;
}
int power(int a, int b, int res = 1) {for(; b; a = a * a % mod, b >>= 1) if(b & 1) res = res * a % mod; return res;}
/*----------------------------------------函数*/
signed main() {
	n = read(); m = read();
	for(int i = 1; i <= m; i++) add_edge(read(), read());
	for(int i = 1; i <= n; i++) if(!g[i]) dfs(i);
	printf("%lld", sum1 * power(sum2, mod - 2) % mod);
	return 0;
}

6. \(P1297\) 单选错位

考虑 \(a_i\)\(a_{i + 1}\) 两个位置

\(a_i = a_{i + 1}\) 则对第 \(i + 1\) 个位置有 \(\frac 1{a_i}\) 的概率答对

\(a_i < a_{i + 1}\) 则对第 \(i + 1\) 个位置有 \(\frac {a_i}{a_{i + 1}} \times \frac 1{a_i} = \frac 1{a_{i + 1}}\) 的概率答对

\(a_i > a_{i + 1}\) 则对第 \(i + 1\) 个位置有 \(\frac {a_{i + 1}}{a_i} \times \frac 1{a_{i + 1}} = \frac 1{a_i}\) 的概率答对

所以期望为 \(\sum_{i = 1}^n \frac 1{\max\{a_i, a_{i + 1}\}}\) (乘1略去了)

/*
  Time: 5.19
  Worker: Blank_space
  Source: P1297 [国家集训队]单选错位
*/
/*--------------------------------------------*/
#include<cstdio>
#define int long long
#define Max(x, y) ((x) > (y) ? (x) : (y))
/*--------------------------------------头文件*/
const int D = 1e7 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
/*------------------------------------常量定义*/
int n, A, B, C, a[D];
double ans;
/*------------------------------------变量定义*/
inline int read() {
	int x = 0, f = 1; char ch = getchar();
	while(ch < ‘0‘ || ch > ‘9‘) {if(ch == ‘-‘) f = -1; ch = getchar();}
	while(ch >= ‘0‘ && ch <= ‘9‘) {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
	return x * f;
}
/*----------------------------------------快读*/

/*----------------------------------------函数*/
signed main() {
	n = read(); A = read(); B = read(); C = read(); a[n + 1] = a[1] = read();
	for(int i = 2; i <= n; i++) a[i] = (a[i - 1] * A + B) % 100000001;
	for(int i = 1; i <= n + 1; i++) a[i] = a[i] % C + 1;
	for(int i = 1; i <= n; i++) ans += 1.0 / Max(a[i], a[i + 1]);
	printf("%.3lf", ans);
	return 0;
}

期望练习

原文:https://www.cnblogs.com/blank-space-/p/14787105.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!