目录
题目描述
一个箱子里有n个黑球,m个白球,小王想要连续q次从箱子里随机的取出k个球(每次取出k个后立即放回),连续q次取球k个都为黑球的概率是多少,结果对1e9+7取模。
输入描述:
第一行给出一个t,代表t组测试数据。(1<=t<=100000)
每组测试数据给出n,m,k,q。(1<=n,m,k<=1e5,k<=n+m,1<=q<=1e12)
输出描述:
对于每组测试数据输出一个结果代表概率。
示例1
输入
2 2 2 1 2 3 3 2 1
输出
250000002 400000003
说明
第一个样例结果为1/4,取模为1*4^(mod-2)%mod=250000002。
思路:
1,要预处理阶乘,用公式简化算法
2,后悔没学好高中数学,p=c(n,k)/c(n+m,k)%mod,重复此过程q次
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i,m,n) for(int i=m;i<=n;++i)
; const int maxj =1e5+100,mod = 1e9+7;
template<class t> void read(t & res) {
char c;t flag=1;
while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
}
int a[maxj];
int ksm(int a,int b){//log级别的
int ans=1;
while(b){
if(b&1){
ans=ans*a%mod;
}
a=a*a%mod;
b>>=1;
}
return ans;
}
int c(int n,int m){
return a[n]*(ksm(a[n-m]*a[m]%mod,mod-2)%mod)%mod;
}
void init(){//应该提前处理阶乘,而不是线性逆元
a[0]=a[1]=1;
rep(i,2,maxj-100){
a[i]=i*a[i-1]%mod;
}
}
int32_t main(){
int t;
read(t);
init();
while(t--){
int n,m,k,q;
read(n),read(m),read(k),read(q);
if(k>n){cout<<0<<'\n';continue;}
int r1=c(n,k);
int r2=c(n+m,k);//排列组合
int ans=r1*ksm(r2,mod-2)%mod;
cout<<ksm(ans,q)%mod<<'\n';
}
return 0;
}