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;
}
posted @ 2025-09-19 11:47  WuMin4  阅读(14)  评论(0)    收藏  举报