概率dp.

dp 求概率

这类题目采用顺推,也就是从初始状态推向结果。同一般的 DP 类似的,难点依然是对状态转移方程的刻画,只是这类题目经过了概率论知识的包装。---OI

走路2 - 题目 - Daimayuan Online Judge

 用vector<int>h[N]来存储每一个点能够通向的点,那么该点去往其他点的概率

p = 1/h[i].size() 

在从起点开始遍历每一个点,到达一个点的概率为其父亲节点的概率和

ps:题目要求取模,运用逆元 ,可预处理逆元,优化时间

inline void slove()
{
	int n = read(),m=read();
	V<int>h[101];
	for (int i = 1; i <= m; i++)
	{
		int x=read(), y=read();
		h[x].push_back(y);
	}
//自己走到自己概率一定为1
	dp[1] = 1;
	for (int i = 1; i < n; i++)
	{
		int m = h[i].size();
		for (int j = 0; j < m; j++)
		{
             //h[i][j]为去往的点  通往每个点的概率为 (1/m)%mod
			dp[h[i][j]] += dp[i] * ksm(m, mod - 2);
			dp[h[i][j]] %= mod;
		}
	}
	printf("%lld", dp[n]);
}

dp求期望

(从终点逆推到起点)

走路3 - 题目 - Daimayuan Online Judge 

 对于从起点开始顺推,情况多种,不一定能到达终点,采取逆推方式更简单

对于每一个点的期望 E=dp[i] = Σ(1->m) (dp[j]+1)/m  = (Σ(1->m) dp[j]/m )+ 1;  

inline void slove()
{
	int n = read(),m=read();
	V<int>h[101];
	for (int i = 1; i <= m; i++)
	{
		int x=read(), y=read();
		h[x].push_back(y);
	}
	//求期望是 终点—>起点的顺序
	//dp[n] 路数是0 dp[n]=0;
	for (int i = n-1; i; i--)
	{
		int m = h[i].size();
		// i—>j  的概率是 1/m 路数是 j->n的路数加 1
		dp[i] = 1;
		for (int j : h[i])
		{
			dp[i] += dp[j] * ksm(m, mod - 2);
			dp[i] %= mod;
		}
	}
	cout <<dp[1] << endl;
}

很多期望dp可采取类似的理解来解决

类似的理解ps:一个点他有多个子节点,要遍历所有子节点来求出其期望

例如:

瓜子 - 题目 - Daimayuan Online Judge

在第二层for循环中,遍历的是 第i个瓜子找到后,还剩下多少个瓜子壳(最多2*n-2*i个瓜子壳,运气很好,全拿的瓜子,没有丢弃瓜子壳   。最少为0 运气很差,一直在丢吃过的瓜子的壳)

// 剩下 i 个瓜子,j 个瓜子壳 期望多少次拿完 dp[0][j]=0
ll dp[N][2 * N];
int a[2 * N];
inline ll ksm(ll a, int b)
{
	ll ans = 1;
	while (b) {
		if (b & 1)
			ans = (ans * a) % mod;
		a = (a * a) % mod;
		b /= 2;
	}
	return ans;
}

inline void slove()
{
	int n = read();
	for (int i = 1; i <= 2 * n; i++)
		a[i] = ksm(i, mod - 2);
	for (int i = 1; i <= n; i++)
	{
		//遍历 第i个瓜子后 有多少个子情况 
		for (int j = 0; j<=2*n-2*i; j++)
		{
            //拿到了瓜子,剩下瓜子数-1 瓜子壳+2
			dp[i][j] += dp[i - 1][j + 2] * i % mod * (ll)a[i + j] % mod;
			dp[i][j] = (dp[i][j] + 1) % mod;
			if (j)
                //拿到瓜子壳,剩下瓜子壳-1
				dp[i][j] += dp[i][j - 1] * j % mod * (ll)a[i + j] % mod;
		}
	}
	cout << dp[n][0] << endl;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zzz0929_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值