比赛时A了这道题,感觉很有意思。
一道期望dp,比较好玩。
Description
Data Constraint
题解
期望dp多为逆推,我们从逆推的方向去想一想:
设
f
[
i
]
f[i]
f[i]表示从
i
i
i颗星到n颗星的期望局数。
容易推出方程:
f
[
i
]
=
p
[
i
]
f
[
i
+
1
]
+
(
1
−
p
[
i
]
)
f
[
i
−
1
]
+
1
f[i]=p[i]f[i+1]+(1-p[i])f[i-1]+1
f[i]=p[i]f[i+1]+(1−p[i])f[i−1]+1
发现有后效性,仔细观察得出:
f
[
n
]
=
0
,
f
[
n
−
1
]
=
(
1
−
p
[
n
−
1
]
)
f
[
n
−
2
]
+
1
f[n]=0,f[n-1]=(1-p[n-1])f[n-2]+1
f[n]=0,f[n−1]=(1−p[n−1])f[n−2]+1
考虑通过代换的方式代到
f
[
0
]
f[0]
f[0]
f
[
0
]
=
p
[
0
]
f
[
1
]
+
(
1
−
p
[
0
]
)
f
[
0
]
+
1
f[0]=p[0]f[1]+(1-p[0])f[0]+1
f[0]=p[0]f[1]+(1−p[0])f[0]+1
把
f
[
1
]
f[1]
f[1] 代换掉,然后就成了一个关于
f
[
0
]
f[0]
f[0] 的方程,解一下就好了。
代换的话考虑转移系数和常数项。
具体看代码
Code
#include<cstdio>
#include<iostream>
#define ll long long
using namespace std;
const ll P=998244353;
int n;
ll p[1000005];
template<typename T>void read(T &ss){
ss=0;int ff=1;
char ch=getchar();
for (;!isdigit(ch);ch=getchar()) if (ch=='-') ff=-1;
for (;isdigit(ch);ch=getchar()) ss=(ss<<1)+(ss<<3)+(ch^48);
ss*=ff;return;
}
ll ksm(ll a,ll b){
ll res=1;
for (;b;b>>=1,a=a*a%P)
if (b&1) res=res*a%P;
return res;
}
int main(){
freopen("game.in","r",stdin);
freopen("game.out","w",stdout);
read(n);
ll x,y;
for (register int i=0;i<n;++i){
read(x);read(y);
p[i]=x*ksm(y,P-2)%P;
}
ll a=P+1-p[n-1];
ll b=1;
for (register int i=n-2;i>=1;--i){
ll k=ksm((1-a*p[i]%P+P)%P,P-2);
a=(1-p[i])*k%P;
b=(b*p[i]%P+1)*k%P;
}
if (n==1) a=0,b=0;
printf("%lld\n",(p[0]*b%P+1)%P*ksm((1-a*p[0]%P-1+p[0]+P)%P,P-2)%P);
fclose(stdin);
fclose(stdout);
return 0;
}