HDUOJ 6838 Battle for Wosneth
Problem Description
你在打游戏的时候碰到了如下问题:
有两个人记作Alice和Bob,Bob的生命值为m,Alice的生命值很高,所以可以认为是无限的。两个人的攻击命中率分别为p%,q%。两个人轮流攻击对方。从Alice开始攻击,每次攻击的时候,如果Alice命中,那么能让对方的生命值减低1,同时自己的生命值能恢复1,如果Bob命中,那么能让对方的生命值减低1,注意Bob不会自己回血。
直到Bob的血量变为0,游戏结束。Alice想知道,游戏结束的时候,自己期望生命值变化是多少,对998244353取模。
注意这里的变化量不是绝对值,也就是如果50%的概率加一,50%的概率减一,那么期望的变化量就是0。
对于一个分数a/b,其中gcd(a,b)=1,那么我们认为这个分数对998244353取模的值为一个数c(0≤c<998244353)满足bc≡a(mod998244353)。
Input
第一行一个正整数T(1≤T≤1e4)表示数据组数。
对于每组数据,第一行三个整数m,p,q(1≤m≤1e9,1≤p,q≤100)。
Output
每组测试数据,输出一个数,表示答案。
Sample Input
2
4 100 100
1 50 50
Sample Output
1
499122177
个人是真的讨厌概率题,算得头昏脑胀,关键题解也没说清楚,就说这是一个简单的等比数列求和,我也是一知半解,但是抛开题解我发现可以这么想,把
p
p
p 和
q
q
q 当作攻击力,那么 Alice 一定攻击了
m
m
m 点伤害,也即恢复了
m
m
m 点血,而 Bob 相当于攻击了
m
p
−
1
\frac{m}{p}-1
pm−1 回合,每回合伤害为
q
q
q,所以答案就是
m
−
(
m
p
−
1
)
∗
q
m-(\frac{m}{p}-1)*q
m−(pm−1)∗q,
AC代码如下:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
ll power(ll a,ll b){return b?power(a*a%mod,b/2)*(b%2?a:1)%mod:1;}
int main()
{
int t;
scanf("%d",&t);
ll inv=power(100,mod-2);
while(t--){
ll m,p,q;
scanf("%lld%lld%lld",&m,&p,&q);
p=p*inv%mod;
q=q*inv%mod;
ll ans=m-(m*power(p,mod-2)%mod-1)*q;
if(ans<0) ans=mod-abs(ans)%mod;
printf("%lld\n",ans);
}
return 0;
}