题目描述
题解
因为被BC搞死了所以没有切掉
菜得真实.jpg
先把pq变成概率
设(f[i][j])表示B的生命为i,A的生命为j时A先手的存活概率(反过来的话推出来的式子每次要加常数项搞不了),初值为(f[0][j]=1)
当j=0的时候也是1,可以理解成A先手所以赢了,主要是方便(f[1][1]的)计算(写出来发现是对的)
设(F_i(x)=sum_j f[i][j]x^j),那么有转移
(F_i(x)=p(1-q)F_{i-1}(x)+pqF_{i-1}(x)x+(1-p)(q)F_i(x)x+(1-p)(1-q)F_i(x))
简化式子得到
((1-Cx-D)F_i(x)=(Ax+B)F_{i-1}(x))
(F_i(x)=frac{Ax+B}{1-Cx-D}F_{i-1}(x))
初值(F_0(x)=sum_i x^i=frac{1}{1-x}),求的是(F_m(x)[x^n]),把上下展开暴力卷即可,初值的(frac{1}{1-x})相当于对(frac{1}{Cx+D})做前缀和
这样有个问题,(f[1][0])的值本应该是0但算出来的是B,考虑对(F_1(x))特殊处理
(F_1(x)=(Ax+B)F_0(x)-B+(Cx+D)F_1(x))
(F_1(x)=frac{Ax+B}{1-Cx-D}F_0(x)-frac{B}{1-Cx-D})
形式类似,去掉前缀和即可
时间复杂度O(n+m)
code
#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define C(n,m) (jc[n]*Jc[m]%998244353*Jc[(n)-(m)]%998244353)
#define add(a,b) a=((a)+(b))%998244353
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
#define mod 998244353
#define Mod 998244351
#define ll long long
#define N 200000
//#define file
using namespace std;
ll a[N+1],b[N+1],jc[N+1],Jc[N+1],A2[N+1],B2[N+1],C2[N+1],f[51][51],p,q,A,B,C,D;
int T,n,m,i,j,k,l;
ll qpower(ll a,int b) {ll ans=1; while (b) {if (b&1) ans=ans*a%mod;a=a*a%mod;b>>=1;} return ans;}
ll js(int n,int m1,int m2,bool bz)
{
int i,j,k,l;
ll ans=0;
memset(a,0,(n+1)*8);
memset(b,0,(n+1)*8);
fo(i,0,min(n,m1)) a[i]=A2[i]*B2[m1-i]%mod*C(m1,i)%mod;
fo(i,0,n) b[i]=C2[i]*C(i+m2-1,m2-1)%mod;
if (bz) fo(i,1,n) b[i]=(b[i]+b[i-1])%mod;
fo(i,0,n) ans=(ans+a[i]*b[n-i])%mod;
return ans;
}
int main()
{
#ifdef file
freopen("e.in","r",stdin);
#endif
jc[0]=1;
fo(i,1,N) jc[i]=jc[i-1]*i%mod;
Jc[N]=qpower(jc[N],Mod);
fd(i,N-1,0) Jc[i]=Jc[i+1]*(i+1)%mod;
scanf("%d",&T);
for (;T;--T)
{
scanf("%d%d%lld%lld",&n,&m,&p,&q);
p=p*qpower(100,Mod)%mod,q=q*qpower(100,Mod)%mod;
A=p*q%mod,B=p*(1-q)%mod,C=(1-p)*q%mod,D=(1-p)*(1-q)%mod;
D=qpower(1-D,Mod),A=A*D%mod,B=B*D%mod,C=C*D%mod;
A2[0]=B2[0]=C2[0]=1;
fo(i,1,max(n,m)) A2[i]=A2[i-1]*A%mod,B2[i]=B2[i-1]*B%mod,C2[i]=C2[i-1]*C%mod;
printf("%lld
",((js(n,m,m,1)-js(n,m-1,m,0)*B)%mod+mod)%mod);
}
fclose(stdin);
fclose(stdout);
return 0;
}