期望学习笔记
定义
- 数学期望(mean)(或均值,亦简称期望)是试验中每次可能结果的概率乘以其结果的总和,是最基本的数学特征之一。它反映随机变量平均取值的大小。
- 需要注意的是,期望值并不一定等同于常识中的“期望”——“期望值”也许与每一个结果都不相等。期望值是该变量输出值的平均数。期望值并不一定包含于变量的输出值集合里。
- CSP基本上只出现离散型。
- 如果随机变量只取得有限个值或无穷能按一定次序一一列出,其值域为一个或若干个有限或无限区间,这样的随机变量称为离散型随机变量。
离散型随机变量的一切可能的取值与对应的概率乘积之和称为该离散型随机变量的数学期望(若该求和绝对收敛)。它是简单算术平均的一种推广,类似加权平均。
性质
- 设C为常数,则E(C)=C。
- 设X,Y是任意两个随机变量,则有E(X+Y)=E(X)+E(Y)。(X,Y有一个发生)
- 设X,Y是相互独立的随机变量,则有E(XY)=E(X)E(Y)。(X,Y共同发生)
- 设X是随机变量,C是常数,则E(CX)=CE(X)。
- E(aX+bY)=aE(x)+bE(y)
例题
crossing-river
分析
对于一条河,最小期望通过时间是L/vi,这时人刚到岸边船就来了;最大的期望通过时间是3L/vi,这时人刚到岸边船刚开走。由于期望线性性,平均时间是2L/vi。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<cstring>
#include<algorithm>
#define lson x<<1
#define rson x<<1|1
#define ll long long
#define rint register int
#define mid ((L + R) >> 1)
using namespace std;
template <typename xxx> inline void read(xxx &x) {
char c = getchar(),f = 1;x = 0;
for(;c ^ '-' && !isdigit(c);c = getchar());
if(c == '-') c = getchar(),f = -1;
for(;isdigit(c);c = getchar()) x = (x<<1) + (x<<3) + (c ^ '0');
x *= f;
}
template<typename xxx>void print(xxx x)
{
if(x<0){putchar('-');x=-x;}
if(x>9) print(x/10);
putchar(x%10+'0');
}
const int maxn = 100010;
const int inf = 0x7fffffff;
const int mod = 1e9 + 7;
int n,D;
struct river{
int ks;
double L,vi;
}rv[maxn];
int main()
{
int mk = 0;
while(1) {
++mk;
read(n);read(D);
if(!n && !D) break;
int tem = 0;
double ans = 0;
for(rint i = 1;i <= n; ++i) {
scanf("%d%lf%lf",&rv[i].ks,&rv[i].L,&rv[i].vi);
ans += 2*rv[i].L/rv[i].vi;
tem += rv[i].L;
}
printf("Case %d: %0.3lf\n\n",mk,ans + D - tem);
}
return 0;
}
/*
*/
LOOPS
分析
设dp[i][j]表示从(i,j)到(n,m)的期望消耗,f[i][j][0]/[1]/[2]表示不动,向右,向下的概率。有\(dp[i][j] = f[i][j][0] * dp[i][j] + f[i][j][1] * dp[i][j+1] + f[i][j][2] * dp[i+1][j] + 2\)
整理后为\(dp[i][j] = (dp[i + 1][j] * f[i][j][2] + dp[i][j + 1] * f[i][j][1] + 2) / (1.0 - f[i][j][0])\)
#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<cstring>
#include<algorithm>
#define lson x<<1
#define rson x<<1|1
#define ll long long
#define rint register int
#define mid ((L + R) >> 1)
using namespace std;
template <typename xxx> inline void read(xxx &x) {
char c = getchar(),f = 1;x = 0;
for(;c ^ '-' && !isdigit(c);c = getchar());
if(c == '-') c = getchar(),f = -1;
for(;isdigit(c);c = getchar()) x = (x<<1) + (x<<3) + (c ^ '0');
x *= f;
}
template<typename xxx>void print(xxx x)
{
if(x<0){putchar('-');x=-x;}
if(x>9) print(x/10);
putchar(x%10+'0');
}
const int maxn = 1010;
const int inf = 0x7fffffff;
const int mod = 1e9 + 7;
int n,m;
double f[maxn][maxn][3];
double dp[maxn][maxn];
int main()
{
while(~scanf("%d%d",&n,&m)) {
for(rint i = 1;i <= n; ++i) {
for(rint j = 1;j <= m; ++j) {
scanf("%lf%lf%lf",&f[i][j][0],&f[i][j][1],&f[i][j][2]);//不动,向右,向下
}
}
memset(dp,0,sizeof(dp));
for(rint i = n ; i; --i) {
for(rint j = m; j; --j) {
if(f[i][j][0] == 1) {
continue;//这个点不能动,到达不了(n,m)
}
dp[i][j] = (dp[i + 1][j] * f[i][j][2] + dp[i][j + 1] * f[i][j][1] + 2) / (1.0 - f[i][j][0]);
}
}
printf("%0.3lf\n",dp[1][1]);
}
return 0;
}
/*
*/
扫雷
分析
按常理倒推,dp[i]表示在已翻了i个雷情况下到目标状态还需要的时间,有\(dp[i] = dp[i + 1] * ai / bi + (1 - ai / bi) * dp[0] + 1\)
冒出来一个dp[0]???
做不来咱正着想:设dp[i]为成功扫雷i颗需要的时间,有
\(dp[i] = ai / bi * (dp[i - 1] + 1) + (1 - ai/bi)(dp[i-1] + 1 + dp[i])\)(加上dp[i]表示再来一次)
整理有dp[i] = bi / ai * (dp[i - 1] + 1);
#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<cstring>
#include<algorithm>
#define lson x<<1
#define rson x<<1|1
#define ll long long
#define rint register int
#define mid ((L + R) >> 1)
using namespace std;
template <typename xxx> inline void read(xxx &x) {
char c = getchar(),f = 1;x = 0;
for(;c ^ '-' && !isdigit(c);c = getchar());
if(c == '-') c = getchar(),f = -1;
for(;isdigit(c);c = getchar()) x = (x<<1) + (x<<3) + (c ^ '0');
x *= f;
}
template<typename xxx>void print(xxx x)
{
if(x<0){putchar('-');x=-x;}
if(x>9) print(x/10);
putchar(x%10+'0');
}
const int maxn = 1000010;
const int inf = 0x7fffffff;
const int mod = 1e9 + 7;
ll dp[2],n;
inline ll mp(ll a,ll b) {
ll res = 1;
while(b) {
if(b & 1) res = (res * a) % mod;
a = (a * a) % mod;
b >>= 1;
}
return res;
}
int main()
{
read(n);
for(rint i = 1;i <= n; ++i) {
ll ai,bi;
read(ai);read(bi);
ai = mp(ai,mod-2);
dp[i&1] = (ai%mod*bi%mod*(dp[(i-1)&1] + 1)%mod)%mod;
}
print(dp[n&1]);
return 0;
}
/*
*/
百事世界杯之旅
分析
设dp[i]表示已集齐i种,到达距离n种还要买的期望张数,当前如果买到之前买过的,期望是i / n * dp[i],如果买到没买过的,期望是(n - i) / n * dp[i + 1](所以此方程要倒推),状态转移的代价是1,总结为\(dp[i] = \frac{i}{n} * dp[i] + \frac{n-i}{n} * dp[i + 1] + 1\)
化简有\(dp[i] = dp[i + 1] + \frac{n}{n-i}\)
由于dp[n] = 0,根据数列知识得到最简答案
\(dp[0] = n * (\frac{1}{1} + \frac{1}{2} + ..... + \frac{1}{n})\)
#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<cstring>
#include<algorithm>
#define lson x<<1
#define rson x<<1|1
#define ll long long
#define rint register int
#define mid ((L + R) >> 1)
using namespace std;
template <typename xxx> inline void read(xxx &x) {
char c = getchar(),f = 1;x = 0;
for(;c ^ '-' && !isdigit(c);c = getchar());
if(c == '-') c = getchar(),f = -1;
for(;isdigit(c);c = getchar()) x = (x<<1) + (x<<3) + (c ^ '0');
x *= f;
}
template<typename xxx>void print(xxx x)
{
if(x<0){putchar('-');x=-x;}
if(x>9) print(x/10);
putchar(x%10+'0');
}
const int maxn = 100010;
const int inf = 0x7fffffff;
const int mod = 1e9 + 7;
ll n,up,down,wg;
inline ll gcd(ll a,ll b) {
while(b ^= a ^= b^= a %= b);
return a;
}
int st[maxn],top;
inline void deal(ll tem){
top = 0;
while(tem) {
st[++top] = tem%10;
tem /= 10;
}
return ;
}
int main()
{
read(n);
up = 1;down = 1;
for(rint i = 2;i <= n; ++i) {
ll jj = 1;
ll gg = gcd(down,i);
ll tem = down * i / gg;
up = tem / down * up;
jj = tem / i * jj;
up += jj;down = tem;
while(up > down) {
up -= down;
++wg;
}
jj = gcd(up,down);
up /= jj;down /= jj;
}
wg *= n;
up *= n;
while(up > down) {
up -= down;
++wg;
}
if(up == down) print(++wg);
else {
ll tem = gcd(up,down);
up /= tem;
down /= tem;
deal(wg);
while(top) putchar(' '),--top;
deal(up);tem = top;
while(top) print(st[top]),--top;putchar('\n');
deal(down);
if(top > tem) tem = top;
print(wg);
while(tem) putchar('-'),--tem;putchar('\n');
deal(wg);
while(top) putchar(' '),--top;
deal(down);
while(top) print(st[top]),--top;
}
return 0;
}
/*
*/