一 ,一个for的求法
求的组合的数量不多的时候
#include<iostream>
using namespace std;
int main(){
int n,k,i;
long long ans;
while(cin>>n>>k){
if(k==0&&n==0) break;
if(n-k<k) k=n-k;//如Cn4 = Cn2(n==6时),此时的我们选择k比较小的那个即k=n-k;
ans=1;//乘法的初始要是 1
for(i=1;i<=k;++i)ans=ans*(n-i+1)/i;
cout<<ans<<endl;
}
}
二,杨辉三角求组合数
适合批量求很多的时候
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn=10000;
ll C[maxn][maxn];
int main()
{
memset(C,0,sizeof(C));//初始化
ll i,j,N;
cin>>N;//表示计算到C N1到 C NN
for(i=0;i<=N;i++){//注意i 从零开始
C[i][0]=1;//每行的头第一个初始化为 1
for(j=1;j<=i;j++){
C[i][j]=C[i-1][j]+C[i-1][j-1];//上面的元素+上面元素的左边元素
}
}
for(i=0;i<=N;i++){//输出杨辉三角
for(j=0;j<=N;j++){
printf("%lld ",C[i][j]);
}
printf("\n");
}
}
三,预处理组合数加上逆元
#include<iostream>
using namespace std;
typedef long long ll;
const ll maxn=1e6+20;
ll fact[maxn];
ll infact[maxn];//保存着阶乘的逆元
const ll mod=1000000007;
ll suan(ll base,ll zhi)
{
ll ans=1;
while(zhi){
if(zhi&1){
ans=base*ans%mod;
}
zhi=zhi>>1;
base=base*base%mod;
}
return ans;
}
void chuli()
{
fact[0]=infact[0]=1;//0的阶乘是1
for(int i=1;i<=maxn;i++){
fact[i]=i*fact[i-1]%mod;
infact[i]=infact[i-1]*suan(i,mod-2)%mod;//suan计算逆元
}
}
int main()
{
int n,m;
ll cnt;
chuli();
while(cin>>n>>m){//组合C n m
cnt=fact[n]*infact[n-m]%mod*infact[m]%mod;
cout<<cnt<<endl;
}
}