牛客35627C - Card

链接:https://ac.nowcoder.com/acm/contest/35627/C 知识点:概率期望 难度:蓝

题意

有 C 张金卡,S 张禁卡,B 张炸弹卡。 现在不放回地抽卡, 若取到金卡则继续抽卡, 若取到禁卡则立即停止抽卡, 若取到炸弹卡,则清空之前取到的所有金卡并立即停止抽卡。 求抽卡停止时,取到金卡数量的期望。

思路

考虑期望的线性可加性。

什么是期望的线性可加性?

E=1×P1+2×P2+3×P3+...+n×PnE=事件1对期望的贡献\times P_1+事件2对期望的贡献\times P_2+事件3对期望的贡献\times P_3+...+事件n对期望的贡献\times P_n 需要注意的是:期望的线性可加性在使用前,要注意确保这些事件彼此相互独立,互不影响。

这些题目可以让你练手: CF280C、洛谷4316、洛谷3232、洛谷6835

事件的确定、概率的计算

既然是求取到金卡数量的期望,咱们一定要从金卡下手。 禁卡、爆炸卡...太复杂,咱们不妨先将所有卡分为两类: 好卡(金卡)和坏卡(禁卡和爆炸卡) 就以好卡的最小单位,1张好卡下手,设事件为这张好卡在坏卡被抽到之前 被抽到, 那么在这种情况下,这张卡是一定能对期望做出 11 的贡献。 此事件发生的概率 P=1B+S+1P=\frac{1}{B+S+1}

为什么是P=1B+S+1P=\frac{1}{B+S+1}? 因为这是不可放回地抽。

如果,如果,炸弹卡不具备清空金卡的作用,那么答案就是 E=C×1B+S+1E=C\times \frac{1}{B+S+1} 注意:实际上炸弹能清空金卡,那么如果很不幸最后抽到的那一张为炸弹卡(发生的概率为 BB+S\frac{B}{B+S}),那么直接就是 00。 所以,最终的答案 ans=C×1B+S+1×(1BB+S)ans=C\times \frac{1}{B+S+1}\times(1-\frac{B}{B+S})

代码

#include <cstdio>
#include <iostream>
#define int long long
const int N	= 1e6+10;
const int MOD	= 1e9+7;
using namespace std;

long long POW(long long a,long long b)
{
	long long ans=1;
	while(b>0)
	{
		if(b&1)
		{
			ans*=a, ans%=MOD;
		}
		a*=a, a%=MOD;
		b>>=1;
	}
	return ans;
}
int Inv(int a,int b)
{
	return a*POW(b, MOD-2)%MOD;
}

int Gold,Proh,Bomb;
int T;

void Solve()
{
	if(Proh==0&&Bomb==0)
	{
		printf("%lld\n",Gold);
		return;
	}
	//禁止牌在炸弹牌之前被抽到
	int tmp1 = Inv(Proh, (Proh+Bomb)%MOD);
	
	//某一张金牌在禁止牌和炸弹牌之前被抽到
	int tmp2 = Inv(1, (Proh+Bomb+1)%MOD);
	
	int ans = Gold * tmp2 % MOD * tmp1 % MOD;
	
	printf("%lld\n",ans);
}

signed main()
{
	scanf("%lld",&T);
	while (T--)
	{
		scanf("%lld %lld %lld",&Gold,&Proh,&Bomb);
		Solve();
	}
	return 0;
}