题意
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
",1.0-ans);
return 0;
}