P8967 追寻 | Pursuit of Dream 题解

传送门

我的不乐观

题解

为便于表述,下文称第 \(i\) 个可以散入天际到的点为第 \(i\) 天际点,特别的,起点为第 \(0\) 天际点,\(P=\sum p_i\)

看到恐怖的 \(\sum d_i \le 10^7\) 就知道不能所有点都讨论了。考虑设 \(dp_i\) 表示第 \(i\) 天际点到终点的期望步数,我们把贡献拆开,先只计算天际点到终点不经过散入天际的期望步数。

不散入天际的期望

假设现在在算第 \(i\) 天际点的期望步数,首先注意到步数一定是:

\[\sum_{j=1}^{n} d_{j}-a_{i,j} \]

所以只用算出概率然后乘起来算贡献即可,我们令 \(s_i\) 等于到终点的步数。

那么可以转化问题为有 \(s_i\) 个球,把它们放入 \(n\) 个盒子中(每一步都有 \(n\) 种选择),求第 \(j\) 个盒子刚好有 \(d_j-a_{i,j}\) 个球的概率,于是这就是 lmx 小学二年级就会的概率期望入门了,答案显然就是(\((1-P)^{s_i}\) 表示 \(s_i\) 步不散入天际的概率):

\[\frac{s_i!}{\prod_{j=1}^{n}(d_j-a_{i,j})!\times n^{s_i}} \times (1-P)^{s_i} \]

然后我们把这个答案用 \(q\) 数组存起来,特别的,当有任意 \(d_j < a_{i,j}\) 时,\(q_i=0\)

引入散入天际

为避免 \(dp_i\) 的转移式中出现其他 dp 值,考虑设 \(g\) 表示散入天际后的期望步数,那么显然:

\[g=\sum_{i=1}^{k}\frac{p_i}{P}dp_i \]

然后第 \(i\) 天际点乱走直到散入天际的期望就是 \(\frac{1}{P}\)。但有可能走到一半走到终点了,应该减掉,走到终点的期望步数为 \(q_is_i\),而走到终点后散入天际的期望为 \(q_i\frac{1}{P}\),于是最后从第 \(i\) 天际点出发直到散入天际的期望就是:

\[\frac{1}{P}-q_i*\left(\frac{1}{P}+s_i\right) \]

于是有

\[dp_i=q_is_i+\left(1-q_i\right)g+\frac{1}{P}-q_i*\left(\frac{1}{P}+s_i\right) \]

然后来解 \(g\),代入有:

\[g=\sum_{i=1}^{k}\frac{p_i}{P}\times\left (q_is_i+\left (1-q_i\right )g+\frac{1}{P}-q_i*\left (\frac{1}{P}+s_i\right )\right ) \]

移项整理得:

\[P\left (1+\sum_{i=1}^k\frac{p_i}{P}\left (q_i-1\right )\right )g=\sum_{i=1}^k\frac{p_i}{P}\left (1-q_i\right ) \]

也就是:

\[g=\frac{\sum_{i=1}^k\frac{p_i}{P}\left (1-q_i\right )}{P\left (1+\sum_{i=1}^k\frac{p_i}{P}\left (q_i-1\right )\right )} \]

然后答案(\(dp_0\))就是:

\[q_0 s_0+\left(1-q_0\right)g+\frac{1}{P}-q_0*\left(\frac{1}{P}+s_0\right) \]

实际代码中不需要 \(dp\) 数组。

code

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=998244353;
int n,k,d[10010],a[10010][110],x[10010],fac[10010000],p[10010],q[10010],s[10010],fl[10010],P,g;
int qpow(int x,int y){
	int aaa=1;
	while(y){
		if(y&1){
			aaa=aaa*x%mod;
		}
		x=x*x%mod;
		y>>=1;
	}
	return aaa;
}
signed main(){
	fac[0]=1;
	for(int i=1;i<=10000000;i++){
		fac[i]=fac[i-1]*i%mod;
	}
	cin>>n>>k;
	for(int i=1;i<=n;i++){
		cin>>d[i];
		s[0]=(s[0]+d[i])%mod;
	}
	for(int i=1;i<=k;i++){
		for(int j=1;j<=n;j++){
			cin>>a[i][j];
			if(a[i][j]>d[j]){
				fl[i]=1;
			}
			s[i]=(s[i]+d[j]-a[i][j])%mod;
		}
		cin>>p[i];
		p[i]=p[i]*qpow(1e8,mod-2)%mod;
		P=(P+p[i])%mod;
	}
	for(int i=0;i<=k;i++){
		if(fl[i]){
			q[i]=0;
			continue;
		}
		int su=1;
		for(int j=1;j<=n;j++){
			su=su*fac[((d[j]-a[i][j])%mod+mod)%mod]%mod;
		}
		q[i]=fac[s[i]]*qpow(su*qpow(n,s[i])%mod,mod-2)%mod*qpow((1-P+mod)%mod,s[i])%mod;
	}
	int zuo=1,you=0;
	for(int i=1;i<=k;i++){
		zuo=(zuo+p[i]*qpow(P,mod-2)%mod*(q[i]-1)%mod)%mod;
		you=(you+p[i]*qpow(P,mod-2)%mod*(((qpow(P,mod-2)-qpow(P,mod-2)*q[i]%mod+mod)%mod)%mod)%mod)%mod;
	}
	g=you*qpow(zuo,mod-2)%mod;
	cout<<(((1-q[0])%mod+mod)%mod*((g+qpow(P,mod-2))%mod)%mod+mod)%mod;
	return 0;
}
posted @ 2025-03-08 16:55  LEWISAK  阅读(37)  评论(0)    收藏  举报