Sugoroku 4 (Atcoder abc275 T5) DP

题目描述

题目链接 https://atcoder.jp/contests/abc275/tasks/abc275_e

题意

\(0\)\(n\)\(n+1\) 个方格,你现在在第 \(0\) 个格子。
每次移动可以随机走 \(1\)\(m\) 个格子,如果走到第 \(n\) 个格子后还没走完,就后退继续走。
求最多移动 \(k\) 次走到第 \(n\) 个格子的概率,对 \(998244353\) 取模。

\(M≤N≤1000\)
\(1≤M≤10\)
\(1≤K≤1000\)

题目分析

不难发现,可以构建dp数组,\(f[i][j]\) 表示第 \(i\) 次移动后在第 \(j\) 个方格的概率。
那么这样做的时间复杂度就为 \(O(nmk)\)

代码

分数取模部分使用乘法逆元

#include <bits/stdc++.h>
using namespace std;
const int N=1e3+5;
const int P=998244353;
int n,m,k,inv[N],f[N][N],ans;
int main(){
	scanf("%d%d%d",&n,&m,&k);
	inv[1]=1;
	for(int i=2;i<=m;i++) inv[i]=(1ll*(P-P/i)*inv[P%i])%P;
	f[0][0]=1;
	for(int i=1;i<=k;i++){
		for(int j=0;j<=n;j++){
			for(int l=1;l<=m;l++){
				int pos=j+l;
				if(pos>n) pos=n-(pos-n);
				f[i][pos]=(1ll*f[i][pos]+1ll*f[i-1][j]*inv[m])%P;
			}
		}
		ans=(1ll*ans+f[i][n])%P;
		f[i][n]=0;
	}
	printf("%d",ans);
	return 0;
}
posted @ 2022-11-04 13:07  KevinLikesCoding  阅读(29)  评论(0编辑  收藏  举报