题目链接:登录—专业IT笔试面试备考平台_牛客网
题目:


样例1输入:
- 30 5 0 0 0 0 0 0
- 30 5 0 0 0 0 0 0
样例1输出:
499122177
样例2输入:
- 10 0 0 0 0 0 0 0
- 11 0 0 0 0 0 0 0
样例2输出:
748683265
简化题意:两个将领,一个是A,一个是B,每个将领带领若干个小兵,每个将领带的小兵个数最多有七个,每个人物有一个初始血量,然后每秒随机选择一个人物扣10滴血,可能是将领也可能是小兵,如果A将领比B将领先死那么A将领失败,否则获胜。求A将领获胜的概率。
分析:其实这道题目跟小兵的血量以及个数是没有关系的,因为小兵的作用只是降低一开始将领的中枪概率,但是在两个将领均存活阶段两个将领的中枪概率始终是相同的,所以小兵只会延长将领死去的时间,但不会影响将领死亡的顺序,也就是说不会对概率造成影响,所以我们一开始直接看成只有两个将领即可,每个将领减10滴血的概率均为1/2,假如A将领经过t1次攻击后会死,B将领经过t2次攻击后会死,那么我们就枚举B将领遭受t2-1次攻击时A将领遭受的攻击次数即可,最后直接再让B将领遭受一次攻击,其中若想要A将领获胜,则B将领遭受t2-1次攻击时A将领遭受的攻击次数的范围为0~t1-1,假如A将领遭受了x次攻击,那么就一共有x+tb-1次攻击,其中每种方案的概率都是1/(2^(x+tb-1)),这种方案的方案数有C(x+tb-1,tb-1),最后还需要直接攻击B将领一次,概率为1/2.那么对应的概率贡献就是C(x+tb-1,tb-1)*qpow(p2[x+tb],mod-2),那么我们枚举一下每个方案的概率就可以求得所有B将领死在A将领前面的方案概率和了。
细节见代码:
- #include<cstdio>
- #include<iostream>
- #include<algorithm>
- #include<cstring>
- #include<map>
- #include<queue>
- #include<vector>
- #include<cmath>
- using namespace std;
- const int N=2e7+10,mod=998244353;
- typedef long long ll;
- ll fac[N],inv[N],p2[N];
- ll qpow(ll a,ll b)
- {
- ll ans=1;
- while(b)
- {
- if(b&1) ans=ans*a%mod;
- b>>=1;
- a=a*a%mod;
- }
- return ans;
- }
- ll C(ll a,ll b)
- {
- return fac[a]*inv[b]%mod*inv[a-b]%mod;
- }
- int main()
- {
- long long a,b,t;
- cin>>a;
- for(int i=1;i<=7;i++)
- cin>>t;
- cin>>b;
- for(int i=1;i<=7;i++)
- cin>>t;
- ll ta=(a-1)/10+1,tb=(b-1)/10+1;
- inv[0]=fac[0]=p2[0]=1;
- for(int i=1;i<=ta+tb;i++)
- {
- fac[i]=fac[i-1]*i%mod;
- p2[i]=p2[i-1]*2%mod;
- }
- inv[ta+tb]=qpow(fac[ta+tb],mod-2);
- for(int i=ta+tb-1;i>=1;i--)
- inv[i]=inv[i+1]*(i+1)%mod;
- ll ans=0;
- for(int i=0;i<ta;i++)
- ans=(ans+C(i+tb-1,tb-1)*qpow(p2[i+tb],mod-2)%mod)%mod;
- cout<<ans;
- return 0;
- }