“蔚来杯“2022牛客暑期多校训练营10-H Wheel of Fortune

原题题面:https://ac.nowcoder.com/acm/contest/33195/H

题目大意

你的血量为 A ( 0 < A ≤ 1 0 7 ) A(0A(0<A107),拥有最多 7 7 7个随从,血量分别为 a i , a 2 , ⋅ ⋅ ⋅ , a 7 a_i,a_2,···,a_7 ai,a2,⋅⋅⋅,a7( a i ≥ 0 a_i\ge0 ai0,若随从不存在则 a i = 0 a_i=0 ai=0 0 ≤ a i ≤ 1 0 7 0\le a_i\le 10^7 0ai107)。
同时,你对手的血量为 B ( 0 < B ≤ 1 0 7 ) B(0< B\le 10^7) B(0<B107),拥有最多 7 7 7个随从,血量分别为 b i , b 2 , ⋅ ⋅ ⋅ , b 7 b_i,b_2,···,b_7 bi,b2,⋅⋅⋅,b7( b i ≥ 0 b_i\ge0 bi0,若随从不存在则 b i = 0 b_i=0 bi=0 0 ≤ b i ≤ 1 0 7 0\le b_i\le 10^7 0bi107)。

现在触发了燃烧之路,其效果等价于以下随机过程:

  • 重复以下操作直到 A ≤ 0 A\le0 A0 B ≤ 0 B\le0 B0:从 A , B , a 1 , a 2 , ⋅ ⋅ ⋅ , a 7 , b 1 , b 2 , ⋅ ⋅ ⋅ , b 7 A,B,a_1,a_2,···,a_7,b_1,b_2,···,b_7 A,B,a1,a2,⋅⋅⋅,a7,b1,b2,⋅⋅⋅,b7中随机选择一个大于零的元素 x x x,然后 x ⟵ x − 10 x\longleftarrow x-10 xx10
  • 如果 B ≤ 0 B\le0 B0,则你获胜;否则你的对手获胜;

求你获胜的概率(答案对 998244353 998244353 998244353取模)。

解题思路

首先,对于每一个随从的攻击不影响最终获胜的概率,对任何随从的攻击相当于白费一次机会。

为了方便起见设 a = ⌈ A 10 ⌉ , b = ⌈ B 10 ⌉ a=\left\lceil\dfrac{A}{10}\right\rceil,b=\left\lceil\dfrac{B}{10}\right\rceil a=10A,b=10B,当操作回合数为 b b b A A A获胜的概率为 1 2 b \dfrac{1}{2^b} 2b1 b + 1 b+1 b+1时,概率为之前 b b b个取了 b − 1 b-1 b1个,这次又取了 1 1 1个,概率为 C b b − 1 2 b × 1 2 \dfrac{C_{b}^{b-1}}{{2^b}}\times\dfrac{1}{2} 2bCbb1×21 b + 2 b+2 b+2时,概率为 C b + 1 b − 1 2 b + 1 × 1 2 \dfrac{C_{b+1}^{b-1}}{2^{b+1}}\times\dfrac{1}{2} 2b+1Cb+1b1×21······以此类推,第 b + i b+i b+i时,概率为 C b + i − 1 b − 1 2 b + i − 1 × 1 2 = C b + i − 1 b − 1 2 b + i \dfrac{C_{b+i-1}{b-1}}{2^{b+i-1}}\times\dfrac{1}{2}=\dfrac{C_{b+i-1}{b-1}}{2^{b+i}} 2b+i1Cb+i1b1×21=2b+iCb+i1b1,所以A总的获胜概率为:
P = ∑ i = 0 a C b + i − 1 b − 1 2 b + i P=\sum_{i=0}^a\dfrac{C_{b+i-1}^{b-1}}{2^{b+i}} P=i=0a2b+iCb+i1b1

代码实现

#include
using namespace std;
const int mod=998244353,N=16e6+5;
int A,B,a[10],b[10],n=7;
int dp[15],fac[N],inv[N],res,cnt,_a,_b,ans;
int fpow(int x,int p){for(res=1;p;x=1ll*x*x%mod,p>>=1)if(p&1)res=1ll*res*x%mod;return res;}
int C(int a,int b){
	return 1ll*fac[b]*fpow(fac[a],mod-2)%mod*fpow(fac[b-a],mod-2)%mod;
}
void init(){//预处理阶乘
	fac[0]=fac[1]=1;
	for(int i=2;i<=N;i++)fac[i]=1ll*fac[i-1]*i%mod;
}
int main(){
	init();
	cin>>A;A=(A-1)/10+1;
	for(int i=1;i<=n;i++)cin>>a[i];
	cin>>B;B=(B-1)/10+1;
	for(int i=1;i<=n;i++)cin>>b[i];
	for(int i=0;i<A;i++){
		ans=(1ll*ans+1ll*C(B-1,B+i-1)*fpow(fpow(2,B+i),mod-2)%mod)%mod;
	}
	cout<<ans;
}

你可能感兴趣的:(算法,c++,概率论)