CF107B Basketball Team

题意

yft所在的学校有 \(m\) 个社团,他所在的社团编号是 \(h\) 。现在yft受wjx命令需要从这 \(m\) 个社团中随机挑出 \(n\) 个人(\(n\) 个人包括他自己),请问挑出的人存在和yft同社团的概率是多大。

Solution

我们先考虑如果正着去选择可能的情况,\(\cdots\) ,发现是很麻烦的,所以我们要正难则反

统计不可能的情况,最后用 \(1\) 减去即可。

\(sum\) 为总人数,那么从 \(sum-1\)\(n-1\) 个人是总情况数,从 \(sum-a[h]\)\(n-1\) 个人是不可能的情况。

\(ans=1-\dfrac{C_{sum-a[h]}^{n-1}}{C_{sum-1}^{n-1}}\) ,因为两个组合数的分母部分相同,可以继续化简: \(ans=1-\dfrac{(sum-a[h])*(sum-a[h]-1)\cdots (sum-a[h]-n-1)}{(sum-1)*(sum-2)\cdots (sum-n-2)}\)

代码

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;
const int N=10010;
int n,m,h,a[N],sum;

inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)){x=x*10+(ch^48);ch=getchar();}
    return x*f;
}

int main(){
    scanf("%d%d%d",&n,&m,&h);
    for(int i=1;i<=m;i++)
        scanf("%d",&a[i]),sum+=a[i];
    if(sum<n){
        puts("-1");
        return 0;
    }
    if(sum-a[h]<(n-1)){
        puts("1");
        return 0;
    }
    double ans=1.0;
    double x=sum-a[h],y=sum-1;
    for(int i=1;i<=n-1;i++){
        ans*=x/y;
        x--;y--;
    }
    printf("%.10f\n",1.0-ans);
    return 0;
}
posted @ 2020-09-26 09:26  jasony_sam  阅读(119)  评论(0编辑  收藏  举报