[ABC298E] Unfair Sugoroku 总结

这是一道很好的概率dp的题,适合刚学概率dp的同学。(下面用T代表Takahashi,用A代表Aoki)

这道题需要的变量:T在哪个点、A在哪个点以及下一步该谁走。

所以这道题dp的状态即为:

  • f [ i ] [ j ] [ 0 ] f[i][j][0] f[i][j][0] 表示T在 i i i 点, A在 j j j 点, 下一步该T走时,T赢的概率。

  • f [ i ] [ j ] [ 1 ] f[i][j][1] f[i][j][1] 表示T在 i i i 点, A在 j j j 点, 下一步该A走时,T赢的概率。

考虑完状态,来考虑初值。

概率dp一般都是某个事件必然发生或某个事件不可能发生,那么这道题的初值就是考虑T在什么情况下必赢,在什么情况下必输。

  • 必赢:T已经在n这个点了,不管下一步谁走都赢,即 对于 1 ⩽ i < n 1 \leqslant i < n 1i<n f [ n ] [ i ] [ 0 ] = f [ n ] [ i ] [ 1 ] = 1 f[n][i][0] = f[n][i][1] = 1 f[n][i][0]=f[n][i][1]=1
  • 必输:A已经在n这个点了,不管下一步谁走都输,即 对于 1 ⩽ i < n 1 \leqslant i < n 1i<n f [ i ] [ n ] [ 0 ] = f [ i ] [ n ] [ 1 ] = 0 f[i][n][0] = f[i][n][1] = 0 f[i][n][0]=f[i][n][1]=0

那么状态也就自然而然出来了。

  • f [ i ] [ j ] [ 0 ] = 1 p ∑ i = 1 p f m i n ( i + k , n ) , j , 1 f[i][j][0] = \frac{1}{p}\sum_{i = 1}^pf_{min(i+k, n), j, 1} f[i][j][0]=p1i=1pfmin(i+k,n),j,1
  • f [ i ] [ j ] [ 1 ] = 1 q ∑ i = 1 q f n , m i n ( j + k , m ) , 0 f[i][j][1] = \frac{1}{q}\sum_{i = 1}^qf_{n, min(j+k, m), 0} f[i][j][1]=q1i=1qfn,min(j+k,m),0

那么答案就是 f [ a ] [ b ] [ 0 ] f[a][b][0] f[a][b][0], 即T在 a a a 点, A在 b b b 点, 下一步该T走。

#include <iostream>
#define int long long
using namespace std;
const int NR = 110;
const int MOD = 998244353;
int f[NR][NR][2];
int ksm(int a, int b)
{
	int ans = 1;
	while (b)
	{
		if (b & 1) ans = ans * a % MOD;
		b >>= 1;
		a = a * a % MOD;
	}
	return ans;
}
int inv(int x)
{
	return ksm(x, MOD - 2); // 用费马小定理求逆元
}
signed main()
{
	int n, A, B, P, Q;
	cin >> n >> A >> B >> P >> Q;
	for (int i = 0; i < n; i++)
		f[n][i][0] = f[n][i][1] = 1, f[i][n][0] = f[i][n][1] = 0;
	long long p = inv(P), q = inv(Q);
	for (int i = n - 1; i >= A; i--) // 因为初始位置在A, 所以只枚举到A即可
		for (int j = n - 1; j >= B; j--) // 与i同理
		{
			for (int k = 1; k <= P; k++)
				f[i][j][0] = (f[i][j][0] + f[min(i + k, n)][j][1]) % MOD;
			f[i][j][0] = f[i][j][0] * p % MOD;
			for (int k = 1; k <= Q; k++)
				f[i][j][1] = (f[i][j][1] + f[i][min(j + k, n)][0]) % MOD;
			f[i][j][1] = f[i][j][1] * q % MOD;
 		}
 	cout << f[A][B][0] << '\n';
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值