概率期望问题总结

Posted 桂月二四

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了概率期望问题总结相关的知识,希望对你有一定的参考价值。

1.转化为dp问题。

D - Just another Robbery

哈利波特要去抢银行,第i个银行有mi个金币,有pi的风险率被抓。问总风险率不超过P的情况下最多能抢多少金币。

想要计算风险是比较复杂的,因此我们考虑反面,计算安全率(安全率就是所抢银行的安全率之积,一个银行的安全率=1-pi)。

这就是一个背包问题。计f[i] 为抢到金币i所需的最大安全率

#include <bits/stdc++.h>
#include<ext/rope>
#define pb push_back
#define debug(x) cerr<<#x<<'='<<x<<'\\n'
#define debugg(x,y) cerr<<#x<<'='<<x<<','<<#y<<'='<<y<<'\\n' 
#define FOR(a,b,c) for(int a=(b),a##_end=(c);a<=a##_end;++a)
#define ROF(a,b,c) for(int a=(b),a##_end=(c);a>=a##_end;--a)
#define FASTIO() cin.sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr)
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
using namespace __gnu_cxx;
typedef long long ll;
typedef pair<int,int> PII;
const int N = 200010 ,M = 1000010,mod = 998244353;const double eps = 1e-9;
ll qmi(ll,ll);
template<typename T>inline bool chkmin(T &x,const T &y){return y<x?x=y,1:0;}
template<typename T>inline bool chkmax(T &x,const T &y){return x<y?x=y,1:0;}
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}
int n,m,d;
int a[N];double p[N];
double P;
double f[N];
signed main()
{
	int cas;read(cas);
	int cnt = 0;
	while(cas--)
	{
		printf("Case %d: ",++cnt);
		cin>>P;read(n); P = 1-P; 
		memset(f,0,sizeof f);
		for(int i=1;i<=n;i++)
		{
			scanf("%d%lf",&a[i],&p[i]); 
			p[i] =  1-p[i];
		}
		f[0] = 1;
		for(int i=1;i<=n;i++)
		{
			for(int j=10000;j>=a[i];j--)
				f[j] = max(f[j],f[j-a[i]]*p[i]);
		}
		for(int i=10000;i>=0;i--)
			if(f[i]>=P)
			{
				cout<<i<<'\\n';
				break;
			}
	}    
    return 0;
}

ll qmi(ll a,ll b) {ll res=1;a%=mod;  for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}

2.运用公式计算期望

计E(x) 为从x走到终点所需代价/时间/…/ 的期望,假设x的下一步能够到达的点为x1,x2,…,xk ,所需代价/时间/…/ 为w1,w2,…wk,其概率分别为p1,p2…,pk,那么E(x) = p1*(w1+E(x1))+p2*(w2+E(x2))+…+pk*(wk+E(xk)) ,一般可以采用记忆化搜索来完成。
注意:在有些题目中,p1=p2=…=pk=1/k 公式化简为E(x) = 1/k(w1+E(x1)+w2+E(x2)+…+wk+E(wk))

例1:绿豆蛙的归宿
这里E(x) 代表从点x走到终点路径的期望,E(1)即为答案

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100010,M = 200010;
int ne[M],h[N],e[M],w[M],idx;
int k[N];
double f[N];
void add(int a, int b, int c)  // 添加一条边a->b,边权为c
{
    e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
}
int main()
{
    memset(h, -1, sizeof h);
    int n,m;cin>>n>>m;
    int a,b,c;
    while(m--)
    {
        cin>>a>>b>>c;
        add(b,a,c);
        k[a]++;
    }
    for(int i=n;i>=1;i--)
    {
        for(int j = h[i];~j;j = ne[j])
        {
            int s = e[j];
            f[s]+=1.0/k[s]*(w[j]+f[i]);
        }
    }
    printf("%.2lf",f[1]);
    return 0;
}

例2:Race to 1 Again
题意:每个数字有相等的概率除以自己的某个约数,求这个数变为1的步数期望。
这里的E(x)为数字x变为1步长的期望。
x可以变为x1,x2…,xk (这些数是他的约数,包括1(x1)和本身(xk))
于是E(x) = 1/k *(1+E(x1)+1+E(x2)+…+1+E(xk))
将等式左右乘以k 得 kE(x) = k+E(x1)+E(x2)+…+E(xk)
由于xk就是x ,所以
(k-1) E(x) = k+E(x1)+E(x2)+…+E(xk-1)
于是可以算出E(x)
注意:由于此时x是可以走到本身的,如果不对等式加以处理就会陷入死循环。

#include <bits/stdc++.h>
#include<ext/rope>
#define pb push_back
#define debug(x) cerr<<#x<<'='<<x<<'\\n'
#define debugg(x,y) cerr<<#x<<'='<<x<<','<<#y<<'='<<y<<'\\n' 
#define FOR(a,b,c) for(int a=(b),a##_end=(c);a<=a##_end;++a)
#define ROF(a,b,c) for(int a=(b),a##_end=(c);a>=a##_end;--a)
#define FASTIO() cin.sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr)
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
using namespace __gnu_cxx;
typedef long long ll;
typedef pair<int,int> PII;
const int N = 200010 ,M = 1000010,mod = 998244353;
const double eps = 1e-9;
ll qmi(ll,ll);
template<typename T>inline bool chkmin(T &x,const T &y){return y<x?x=y,1:0;}
template<typename T>inline bool chkmax(T &x,const T &y){return x<y?x=y,1:0;}
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}
int n,m,d;
int a[N];
double ans;
double mp[N];
double dfs(int n)
{
//	debug(n);
//	system("pause");
	if(n==1) return 0;
	if(fabs(mp[n])>eps) return mp[n];
	vector<int> yue;
	for(int i=1;i<=n/i;i++)
	{
		if(n%i==0)
		{
			yue.pb(i);
			if(i!=n/i) yue.pb(n/i);
		}
	}
	int d = yue.size();
	sort(yue.begin(),yue.end());
	double zi = 1;
	for(int i=1;i<d;i++)
	{
		zi+=1+dfs(n/yue[i]);
	}
	return mp[n] = 1.0*zi/(d-1);
}
signed main()
{
	int cas;read(cas);
	int cnt = 0;
	while(cas--)
	{
		read(n);
		printf("Case %d: ",++cnt);
		printf("%.10lf\\n",dfs(n));
	}    
    return 0;
}

ll qmi(ll a,ll b) {ll res=1;a%=mod;  for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}

3.纯数学题(高中数学)

E - Birthday Paradox

给定一年的年数,求最少的人,是的这些人中有两个人生日相同的概率>=0.5
比较简单,可以参考别人的题解
持续更新中…

以上是关于概率期望问题总结的主要内容,如果未能解决你的问题,请参考以下文章

概率期望问题总结

概率期望问题总结

概率期望问题总结

概率期望问题总结

算法总结概率与期望相关

概率论考点总结类型18 求期望