题意:
就是给你小A的血量和小A的7个手下的血量,再给你小B的血量和小B的7个手下的血量。每次随机选择一个血量>0的人,然后让他的血量减10,如果小A或者小B的死了,游戏停止。问你小A获胜的概率是多少。
思考:
- 题目说的随机选择一个人,让血量减10。但这始终是随机的,所以和剩下的14个手下一点关系都没有,所以现在就是小A可以被选a次,小B可以被选b次。求出来总概率就好了。
- 现在就是怎么求总概率了,发现这个小A获胜的情况有a种,分别是肯定选了b次小B,然后小A可能选了0 1 2 3…a-1次。把这些2的i次方求出后,发现概率变大了。这是因为比如选了b次B,1次a那么这个a必须要在前面选,也就是不能先选了b次B再选一次A,因为选完b次B游戏就停止了,所以这种情况是多余的。
- 那么我就想了,把这个转化成球的模型,用子方案/总方案这样求概率,但是还不对,因为此时我把比赛(小球)看成不同的了,其实是相同的,对于某个人而言第一次被选和第二次被选是一样的。所以到这里那么就可以看成球一样的,然后往b次B里面插就好了,但是不能插到最后一个后面,所以一共有b个地方可以插。也就是n球放入m个盒子,球相同盒子不同,盒子可以为空的模型。公式就是C(n+m-1,m-1)。
代码:
#include<bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define db double
#define int long long
#define PII pair<int,int >
#define mem(a,b) memset(a,b,sizeof(a))
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
const int mod = 998244353,inf = 1e18;
const int N = 2e6+10,M = 2010;
int T,n,m,k;
int va[N];
int fact[N],infact[N];
int ksm(int a,int b)
{
int sum = 1;
while(b)
{
if(b&1) sum = sum*a%mod;
a = a*a%mod;
b >>= 1;
}
return sum;
}
void init(int x)
{
fact[0] = infact[0] = 1;
for(int i=1;i<=x;i++) fact[i] = fact[i-1]*i%mod;
infact[x] = ksm(fact[x],mod-2)%mod;
for(int i=x-1;i>=0;i--) infact[i] = infact[i+1]*(i+1)%mod;
}
int C(int a,int b)
{
if(a<b) return 0;
return fact[a]*infact[b]%mod*infact[a-b]%mod;
}
signed main()
{
IOS;
init(2e6+5);
int A,B,x;
cin>>A;
for(int i=1;i<=7;i++) cin>>x;
cin>>B;
for(int i=1;i<=7;i++) cin>>x;
A = (A+10-1)/10;B = (B+10-1)/10;
int ans = 0;
for(int i=0;i<A;i++) //选i个A
{
int up = C(B+i-1,B-1)%mod; //放i个A的方案
int down = ksm(2,B+i)%mod;
ans = (ans+up*ksm(down,mod-2)%mod)%mod;
}
ans = (ans%mod+mod)%mod;
cout<<ans;
return 0;
}
总结:
多多思考,排东西或者放东西的时候,尽量要多想想球和盒子模型。