概率DP&期望杂题

1.http://zhengruioi.com/problem/450

​/*f[i][j]:前i个人,有j个人正常出局的概率

f[i][j]+=f[i-1][j]*P1+f[i-1][j-1]*p2;
        留下来/被日死     正常出局 
p  别人出局后自己被日死的概率 
P2=(1-p)^(j-1);
P1=(1-P1)

f[i][k]*P2 前K个过后都没有被日死
最后再*inv(1/n),这一轮出局概率 */
#include<bits/stdc++.h>
#define rep(i,a,b) for(ll i=(a);i<=(b);i++)
#define ll long long
using namespace std;
const ll mod=258280327;
const ll N=3e3;
ll f[N][N],A[N],B[N],n,x,y,p;
ll power(ll a,ll b){ll ans=1;for(;b;b>>=1,a=a*a%mod)if(b&1)ans=ans*a%mod;return ans;}
int main()
{
	ll t;scanf("%lld",&t);
	while(t--){
		scanf("%lld%lld%lld",&n,&x,&y);
		p=x*power(y,mod-2)%mod;
		A[0]=1;rep(i,1,n)A[i]=A[i-1]*p%mod;
		B[0]=1;rep(i,1,n)B[i]=B[i-1]*((1-p)%mod+mod)%mod;
		memset(f,0,sizeof(f));f[1][0]=1;
		rep(i,2,n)rep(j,0,i-1)f[i][j]=f[i-1][j]*((1-B[j])%mod+mod)%mod+f[i-1][j-1]*B[j-1]%mod;
		rep(i,0,n-1){
			ll ans=0;
			rep(j,1,n)ans=(ans+f[j][i]*B[i])%mod;
			cout<<ans*power(n,mod-2)%mod<<" ";
		}puts(" ");
	}
	return 0;
}​

2.https://www.luogu.org/problemnew/show/CF148D#sub 

/*f[w][b]表示袋子里有w个白的,b个黑的赢得概率
显然 f[][0]=1,f[0][]=0 作为边界,可以记忆化搜索
每次分两种情况:1.A直接取到白球赢的概率 =w/(w+b);
因为先取到白球谁先赢,那么B不能赢
2.A取到黑球, B取到黑球,然后跑出一个黑球
p=b/(w+b)*(b-1)/(w+b-1)*(b-2)/(w+b-2)*f[w][b-3]; (b>=3) 
A取到黑球,B取到黑球,然后跑出一个白球 
p=b/(w+b)*(b-1)/(w+b-1)*w/(w+b-2)*f[w-1][b-2] w&&b>=2*/
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
using namespace std;
const int N=2e3;
int w,b,v[N][N];
double f[N][N];
double work(int w,int b){
	
	if(w==b&&w==0)return 0.0;
	if(b==0)return 1.0;
	if(w==0)return 0.0;
	if(v[w][b])return f[w][b];v[w][b]=1;
	double res=1.0*w/(w+b);
	if(b>=3) res+=(b*1.0/(w+b))*((b-1)*1.0/(w+b-1))*((b-2)*1.0/(w+b-2))*work(w,b-3); 
	if(b>=2) res+=(b*1.0/(w+b))*((b-1)*1.0/(w+b-1))*(w*1.0/(w+b-2))*work(w-1,b-2);
	return f[w][b]=res;
}
int main()
{
	memset(v,0,sizeof(v));
	while(~scanf("%d%d",&w,&b)){
		work(w,b);
		printf("%.9lf\n",work(w,b));
	}
	return 0;
}

3.https://www.luogu.org/problemnew/show/UVA12230

/*有个人每天要去公司上班,每次会经过N条河,家和公司的距离为D,默认在陆地的速度为1,
给出N条河的信息,包括起始坐标p,宽度L,以及船的速度v。船会往返在河的两岸,人到达
河岸时,船的位置是随机的(往返中)。问说人达到公司所需要的期望时间。

因为船的位置是随机的,那我们考虑最长过河时间和最短过河时间
最长:3*L/v;
最短:L/v;
由于算的是期望,那么每条河的期望时间就是
sigma(i=1~3)i*L/v*p; p是概率
我们再观察一下这个式子,这不就是算平均数吗?
那么过每条河的期望时间就等于2*L/v;
然后就可以愉快的计算了*/
#include<bits/stdc++.h>
using namespace std;
int n,D,p,L,v,Case=0;
double ans=0;
int main()
{
	while(~scanf("%d%d",&n,&D)){
		if(n==0&&D==0)return 0;
		ans=0.0;
		while(n--){
			scanf("%d%d%d",&p,&L,&v);
			D-=L;
			ans+=2.0*L/v;
		}
		ans=ans+1.0*D;
		printf("Case %d: %.3lf\n\n",++Case,ans);
	}
	return 0;
}

4.https://www.luogu.org/problemnew/show/SP1026

/*甩一个n面的骰子,问每一面都被甩到的期望次数是多少。
f[i]表示甩出了i~n面的期望次数 
还是倒推吧 
f[i]=(f[i]+1)*i/n+(f[i+1]+1)*(n-i)/n;
移项可得
f[i]=f[i+1]+n/(n-i);
就可以愉快的计算了*/
#include<bits/stdc++.h>
#define per(i,a,b) for(int i=(a);i>=(b);i--)
using namespace std;
double f[2000];
int n,T;
int main()
{
	scanf("%d",&T);
	while(T--){
		scanf("%d",&n);
		f[n]=0;
		per(i,n-1,0)f[i]=f[i+1]+n*1.0/(n-i);
		printf("%.2lf\n",f[0]);
	}
	return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值