qoj1882 Drunkards
SOLUTION FROM WUMIN4
题意
有一个范围为 \([-n,n]\) 的数轴,有一个人初始位于 \(0\),有 \(n\) 步移动,第 \(i\) 步有 \(p\) 的概率不移动,有 \(1-p\) 的概率向 \(a_i\pod{a_i\in \{1,-1\}}\) 方向移动一步。终点等概率位于 \([-n,n]\),问这个人到达过终点的概率为多少。
思路
设 \(f_{i,j}\) 表示还剩 \(i\) 步时从自己的位置开始走到过距离为 \(j\) 的位置的概率。
则显然有 \(f_{i,0}=1\),因为 \(0\) 即为自己的位置。
对于 \(j\neq 0\),有 \(f_{i,j}=f_{i-1,j}\times p+f_{i-1,j+a_{n-i-1}}\times (1-p)\)。
最后 \(\sum_{j=-n}^n f_{n,j}\) 即为答案。
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int md=998244353;
int fpow(int x,int y,int p){
int res=1,t=x;
while(y){
if(y&1) res=(res*t)%p;
t=(t*t)%p,y>>=1;
}
return res;
}
int n,p,pp,a[5005],f[2][10005],ans;
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr),cout.tie(nullptr);
cin>>n>>p;
pp=100-p;
p=p*fpow(100,md-2,md)%md,pp=pp*fpow(100,md-2,md)%md;
for(int i=1;i<=n;i++)
cin>>a[i];
reverse(a+1,a+1+n);
int v=1;
f[0][n+1]=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=2*n+1;j++){
f[v][j]=(f[v^1][j]*p+f[v^1][j-a[i]]*pp)%md;
}
f[v][n+1]=1;
v^=1;
}
for(int i=1;i<=2*n+1;i++)
ans=(ans+f[v^1][i])%md;
ans=ans*fpow(2*n+1,md-2,md)%md;
cout<<ans;
return 0;
}

浙公网安备 33010602011771号