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;
}