Alice打一次加1,概率p%,Bod打一次加1概率q%
他们打一轮,期望得分p%-q%,有几轮哪?
每轮Bod期望掉血p%,所以有m/(p%)轮,注意最后一轮Bod先挂了,没法反击
所以答案是(m/(p%) - 1) * (p%-q%) + 1 * p%
注意m/(p%)不一定是整数,变换一下
(m-p * inv(100)) * (p-q) * inv ( p ) + p * inv(100)
其中inv(i)是mod998244353LL的乘法逆元
#include
#include
using namespace std;
typedef long long ll;
void exgcd(ll a, ll b, ll &x, ll &y) //拓展欧几里得算法
{
if(!b)
x = 1, y = 0;
else
{
exgcd(b, a % b, y, x);
y -= x * (a / b);
}
}
ll Mod = 998244353LL;
ll inv(ll a) //求a对b取模的逆元
{
ll x, y;
ll b = Mod;
exgcd(a, b, x, y);
return (x + b) % b;
}
int main()
{
int T;
scanf("%d", &T);
while (T--) {
int m,p,q;
scanf("%d%d%d",&m,&p,&q);
ll tmp = (m-p*inv(100))%Mod*(p-q)%Mod*inv(p)%Mod;
printf("%lld\n", ((tmp+p*inv(100))%Mod+Mod)%Mod);
}
return 0;
}
你在打游戏的时候碰到了如下问题:
有两个人记作Alice和Bob,Bob的生命值为mmm,Alice的生命值很高,所以可以认为是无限的。两个人的攻击命中率分别为p%,q%p%,q%p%,q%。两个人轮流攻击对方。从Alice开始攻击,每次攻击的时候,如果Alice命中,那么能让对方的生命值减低111,同时自己的生命值能恢复111,如果Bob命中,那么能让对方的生命值减低111,注意Bob不会自己回血。
直到Bob的血量变为000,游戏结束。Alice想知道,游戏结束的时候,自己期望生命值变化是多少,对998244353998244353998244353取模。
注意这里的变化量不是绝对值,也就是如果50%50%50%的概率加一,50%50%50%的概率减一,那么期望的变化量就是000。
对于一个分数a/ba/ba/b,其中gcd(a,b)=1\gcd(a,b)=1gcd(a,b)=1,那么我们认为这个分数对998244353998244353998244353取模的值为一个数c(0≤c<998244353)c(0\leq c < 998244353)c(0≤c<998244353)满足bc≡a(mod998244353)bc\equiv a \pmod {998244353}bc≡a(mod998244353)。
Input
第一行一个正整数T(1≤T≤104)T(1\leq T\leq 10^4)T(1≤T≤104)表示数据组数。
对于每组数据,第一行三个整数m,p,q(1≤m≤109,1≤p,q≤100)m, p, q(1\leq m \leq 10^9, 1\leq p,q\leq 100)m,p,q(1≤m≤109,1≤p,q≤100)。
Output
每组测试数据,输出一个数,表示答案。
Sample Input
2
4 100 100
1 50 50
Sample Output
1
499122177
Hint
第一组数据中,每次都能命中,所以Alice能恢复 4 点生命值,减低 3 点生命值,变化量必定为 1。
第二组数据中,对应的分数为 1/2,在Alice命中Bob之前,Bob能期望命中Alice 1/2 次。