HDUOJ 6838 Battle for Wosneth

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 pm1 回合,每回合伤害为 q q q,所以答案就是 m − ( m p − 1 ) ∗ q m-(\frac{m}{p}-1)*q m(pm1)q
AC代码如下:

#include
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;
}

你可能感兴趣的:(概率期望,HDUOJ)