进球数 概率 组合数学

进球数


题目描述

中超继续进行,广州恒大和北京国安马上开赛了,比赛持续90分钟,为了分析方便,我们把5分钟作为一个时间片,那么比赛会进行18个时间片。在每一个时间片内,恒大踢进1球的概率百分比都是A%,国安踢进1球的概率都是B%。当比赛结束后,两支球队当中,至少有一支球队的进球数是质数的概率是多少?

输入格式

第一行,一个整数R,表示有R组测试数据。1 <= R <= 10。

每组测试数据格式:

第一行,A和B。 0 <= A <= 100, 0 <= B <= 100。

输出格式

共R行,每行一个实数,表示概率。

输入样例

3
50  50
100  100
12  89

输出样例

0.5265618908306351
0.0
0.6772047168840167

解题思路

题目大意:在18个时间片段内至少有一支球队的进球数是质数的概率是多少?

根据题意,简化一下问题,我们先单独考虑一支球队进球数是质数的概率

如果一支球队的进球数为质数,那么这支队的进球数只能是2、3、5、7、11、13、17,继续简化问题,这支球队进球数为2,那么球队在18个时间片段内进2球的情况如下:

情况\时间片段123456……1718
1 √ √ √ √ × × × × × × × × × × × × × × × × × × × × ×
2 √ √ × × × √ √ × × × × × × × × × × × × × × × × × ×
… … …… … … …… … … …… … … …… … … …… … … …… … … …… … … …… … … …… … … ……
18 × × × × × × × × × × × × × × × × × × × × × √ √ √ √

哇!这个表的规模也太大了吧!

这样的情况有多少种呢?能不能通过计算将它算出来呢?仔细观察,我们就可以发现,这不就是组合数嘛!这就相当于从18个小球中选2个: C 18 2 C^{2}_{18} C182

在这18个时间片段中,只有2个时间片段进球,其他时间片段不能进球的情况下才符合当前题意,而这种情况又有 C 18 2 C^{2}_{18} C182种,所以设进球概率为 P ( g o a l ) P(goal) P(goal),球队在18个时间片段内进2球这种情况的概率是: C 18 2 × P ( g o a l ) 2 × ( 1 − P ( g o a l ) ) 16 C^{2}_{18}\times P(goal)^2 \times(1-P(goal))^{16} C182×P(goal)2×(1P(goal))16

由此可知,进球数 i i i相对应的组合数是 C 18 i C^{i}_{18} C18i,概率算法也与上述相同: C 18 i × P ( g o a l ) i × ( 1 − P ( g o a l ) ) 18 − i C^{i}_{18}\times P(goal)^i \times(1-P(goal))^{18-i} C18i×P(goal)i×(1P(goal))18i(组合数可用杨辉三角预处理)。

现在,我们回归到原题,求至少有一支球队的进球数为质数的概率,先分类讨论一下:

  1. 恒大进球数为质数,国安进球数为非质数
  2. 恒大进球数为非质数,国安进球为质数
  3. 恒大进球数为质数,国安进球数为质数

将以上三种情况的概率求出来相加,就是答案了。但是,除此之外还有一种更简单的方法。

至少有一支球队的进球数为质数的概率=1-两支球队进球数都是非质数的概率

这样算就方便多了。


代码:

#include<iostream>
#include<fstream>
#include<algorithm>
#include<iomanip>

using namespace std;
int R,A,B;
long long C[25][25];
int composite[25]={0,1,4,6,8,9,10,12,14,15,16,18};//合数集合
double hd[25],ga[25],temp1,temp2,ans;

void init()
{
	for(int i=0;i<=18;i++)
	{
		C[i][0]=1;
		C[i][i]=1;
	}
	for(int i=1;i<=18;i++)
		for(int j=1;j<i;j++)
			C[i][j]=C[i-1][j-1]+C[i-1][j];
}


int main()
{
	freopen("1265.in","r",stdin);
	freopen("1265.out","w",stdout);
	init();
     cin>>R;
	 for(int r=1;r<=R;r++)
	 {
		 ans=0;
		 cin>>A>>B;
		 for(int i=0;i<=18;i++)
		 {
			temp1=temp2=1;
			for(int j=1;j<=i;j++)
				temp1*=(double(A)*0.01);
			for(int j=1;j<=18-i;j++)
				temp2*=(1.00-double(A)*0.01);
			hd[i]=double(C[18][i])*temp1*temp2;//恒大
			
			temp1=temp2=1;
			for(int j=1;j<=i;j++)
				temp1*=(double(B)*0.01);
			for(int j=1;j<=18-i;j++)
				temp2*=(1.00-double(B)*0.01);
			ga[i]=double(C[18][i])*temp1*temp2;//国安
		 }
		 for(int i=0;i<=11;i++)
			 for(int j=0;j<=11;j++)
				 ans+=hd[composite[i]]*ga[composite[j]];
		 ans=1.00-ans;
		 cout<<fixed<<setprecision(7)<<ans<<endl;
	 }

    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值