题意
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6842
分析
考虑一个二维的 (DP) 模型,每次对连续两轮进行分析。如果两个人都没有打中对方,没有意义。而且最终二者的状态一定是 ((r,1)),然后 (Alice) 一枪把 (Bob) 干掉。所以对于 ((i,j)),有三种后继状态:
- ((i-1,j-1)),转移的概率为 (a=frac{pq}{1-(1-p)(1-q)})
- ((i,j-1)),转移的概率为 (b=frac{p(1-q)}{1-(1-p)(1-q)})
- ((i-1,j)),转移的概率为 (c=frac{(1-p)q}{1-(1-p)(1-q)})
最后,(Alice) 一枪打死 (Bob) 的概率为 (d=frac{p}{1-(1-p)(1-q)})。
我们先计算出 ((n,m) o (r,1)) 的概率,然后再计算 ((r,1) o (r,0)) 的概率。
下面对上述的三种转移方式的次数进行讨论,假设第一种方式的次数为 (x),那么第二种方式的次数为 (m-1-x),第三种方式的次数为 (n-r-x)。令 (i=n-r),则概率如下:
[egin{align}
P & = sum_{i=0}^{n-1}{sum_{x=0}^{min(m-1,i)}{C(m-1+i-x,i-x)·C(m-1,x)·a^x·b^{m-1-x}·c^{i-x}}}
end{align}
]
此时,无法直接处理,考虑改变枚举顺序,同时令第三种方式的次数为 (i),有:
[egin{align}
P & = sum_{x=0}^{min(n-1,m-1)}{C(m-1,x)·a^x·b^{m-1-x}sum_{i=0}^{n-1-x}{C(m-1-i,i)·c^i}}
end{align}
]
令 (S(r)=sum_{i=0}^{r}{C(m-1-i,i)·c^i}),可以预处理。最终答案为:
[egin{align}
P & =d· sum_{x=0}^{min(n-1,m-1)}{C(m-1,x)·a^x·b^{m-1-x}·S(n-1-x)}
end{align}
]
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
const int mod=998244353;
const int inv100=828542813;
ll sum[N],fac[N<<1],inv[N];
int n,m;
ll p,q,a,b,c,d;
ll power(ll x,ll y)
{
ll res=1;
x%=mod;
while(y)
{
if(y&1) res=res*x%mod;
x=x*x%mod;
y>>=1;
}
return res;
}
void init()
{
int maxn=1e5,up=2e5;
fac[0]=1;
for(int i=1;i<=up;i++)
fac[i]=fac[i-1]*i%mod;
inv[maxn]=power(fac[maxn],mod-2);
for(int i=maxn-1;i>=0;i--)
inv[i]=inv[i+1]*(i+1)%mod;
}
ll solve()
{
//预处理sum
sum[0]=1;
ll tc=1;
for(int i=1;i<n;i++)
{
tc=tc*c%mod;
ll ci=fac[m-1+i]*inv[i]%mod*inv[m-1]%mod;
sum[i]=(sum[i-1]+ci*tc%mod)%mod;
}
int minn=min(n-1,m-1);
ll ta=1,tb=power(b,m-1);
ll ans=tb*sum[n-1]%mod;
ll ib=power(b,mod-2);
for(int i=1;i<=minn;i++)
{
ta=ta*a%mod;
tb=tb*ib%mod;
if(i==m-1&&b==0) tb=1;//注意
ll ci=fac[m-1]*inv[m-1-i]%mod*inv[i]%mod;
ans=(ans+ci*ta%mod*tb%mod*sum[n-1-i]%mod)%mod;
}
return ans;
}
int main()
{
int T;
scanf("%d",&T);
init();
while(T--)
{
scanf("%d%d%lld%lld",&n,&m,&p,&q);
p=p*inv100%mod;
q=q*inv100%mod;
ll t=power(1-(1-p)*(1-q)%mod+mod,mod-2);
a=p*q%mod*t%mod;
b=(p*(1-q)%mod*t%mod+mod)%mod;
c=((1-p)*q%mod*t%mod+mod)%mod;
d=p*t%mod;
ll ans=d*solve()%mod;
printf("%lld
",ans);
}
return 0;
}
参考博客:https://www.cnblogs.com/Lanly/p/13473041.html#e-battle-for-wosneth2-hdu-6842