#include<iostream>
using namespace std;
const int N=2010,mod=1e9+7;
int c[N][N];
void init(){//对组合数进行预处理 预处理出组合数(递推)
for(int i=0;i<N;i++){ //i为组合数下面的数
for(int j=0;j<=i;j++){
if(!j) c[i][j]=1;
else c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;//数据会很大 需要在执行时一直求余
}
}
}
int main(){
init();
int n;
scanf("%d",&n);
while(n--){
int a,b;
scanf("%d%d",&a,&b);
printf("%d\n",c[a][b]);
}
return 0;
}
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=100010,mod=1e9+7;
int fact[N],infact[N];
int qmi(int a,int k,int p){
int res=1;
while(k){
if(k&1) res=(LL)res*a%p;
a=(LL)a*a%p;
k>>=1;
}
return res;
}
int main(){
fact[0]=infact[0]=1;
for(int i=1;i<N;i++){//预处理出阶乘
fact[i]=(LL)fact[i-1]*i%mod;
infact[i]=(LL)infact[i-1]*qmi(i,mod-2,mod)%mod;
}
int n;
scanf("%d",&n);
while(n--){
int a,b;
scanf("%d%d",&a,&b);
printf("%d\n",(LL)fact[a]*infact[b]%mod*infact[a-b]%mod);//必须用求逆元 如果用除会进行下取整
}
return 0;
}
此题使用的定理
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
int p;
int qmi(int a,int k,int p){//快速幂
int res=1;
while(k){
if(k&1) res=(LL)res*a%p;
a=(LL)a*a%p;
k>>=1;
}
return res;
}
int C(int a,int b){
if(b>a) return 0;//计算的时候里面肯定有0
if(b>a-b) b=a-b; //利用公式C(a,b)=C(a,a-b)
//法一
// int res=1;
// for(int i=1,j=a;i<=b;i++,j--){//j代表分母 i代表分子
// res=(LL)res*j%p;
// res=(LL)res*qmi(i,p-2,p)%p;
// }
// return res;
//法二 比法一速度快10多倍
int x=1,y=1;
for(int i=0;i<b;i++){//只会比较b次 如果i从1开始 下面要写成a-i+1 i
x=(LL)x*(a-i)%p;
y=(LL)y*(i+1)%p;
}
return (LL)x*qmi(y,p-2,p)%p;
}
int lucas(LL a,LL b){
if(a<p&&b<p) return C(a,b);
return (LL)C(a%p,b%p)*lucas(a/p,b/p)%p;
}
int main(){
int n;
scanf("%d",&n);
while(n--){
LL a,b;
cin>>a>>b>>p;
cout<<lucas(a,b)<<endl;
}
return 0;
}
卡特兰数
注意:如果mod为质数 求逆元快速幂
不为质数 求逆元用扩展欧几里得
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int mod=1e9+7;
int qmi(int a,int k,int p){
int res=1;
while(k){
if(k&1) res=(LL)res*a%p;
a=(LL)a*a%p;
k>>=1;
}
return res;
}
//法一
//int main(){
// int n;
// cin>>n;
// int a=2*n,b=n;
// int res=1;
// for(int i=a;i>a-b;i--) res=(LL)res*i%mod;
// for(int i=1;i<=b;i++) res=(LL)res*qmi(i,mod-2,mod)%mod;
// res=(LL)res*qmi(n+1,mod-2,mod)%mod;
// cout<<res<<endl;
// return 0;
//}
//法二 比法一快20倍
int main(){
int n;
cin>>n;
int a=2*n,b=n;
//求组合数速度最快的代码
int x=1,y=1;
for(int i=0;i<b;i++){
x=(LL)x*(a-i)%mod;
y=(LL)y*(i+1)%mod;
}
cout<<(LL)x*qmi(y,mod-2,mod)%mod*qmi(n+1,mod-2,mod)%mod<<endl;
return 0;
}