1、定义:从m个不同元素中,任取n(n≤m)个元素并成一组,叫做从m个不同元素中取出n个元素的一个组合;从m个不同元素中取出n(n≤m)个元素的所有组合的个数,叫做从m个不同元素中取出n个元素的组合数。
2、公式:在线性写法中被写作C(m,n)。c(m,n)=p(m,n)/n!=m!/((m-n)!*n!)
3、性质:
(1):1.互补性质:组合数性质如上图所示:
即从m个不同元素中取出n个元素的组合数=从m个不同元素中取出(m-n)个元素的组合数。这个性质很容易理解。例如C(9,2)=C(9,7),即从9个元素里选择2个元素的方法与从9个元素里选择7个元素的方法是相等的。
规定:C(m,0)=1
(2):组合恒等式:
若表示在n个物品中选取m个物品,则如存在下述公式: C(n,m)= C(n,n-m)= C(n-1,m-1)+C(n-1,m)。
4、算法
第一种是比较简单的方法,时候数据表较小,分母能够计算出来的时候。
如求C(i,4),(4<=i<=maxn),maxn=10005;
for(i=4;i<maxn;i++)//求组合数,即i个数里面选择4个数的选择的种类有几种。
node[i]=i*(i-1)*(i-2)*(i-3)/24;
第二种是数组求法,利用第二个性质。通常求较大的数,用递归会超时的。
二项式系数C(n, k)满足下面的要求:
C(n, 0) = C(n, n) = 1 for all n > 0;
C(n, k) = C(n − 1, k − 1) + C(n − 1, k) for all 0 < k < n.
题目要求根据给定的n和k(0 ≤ k ≤ n < 231, n > 0)计算C(n,k),典型的递归问题。
但是如果采用递归,当n的值比较大的时候,会堆栈益处。而上面的表达式应该有相应的公式。如果采用公式计算就会变的简单了。
#include<iostream>
using namespace std;
int main()
{
int n,k;
cin>>n>>k;
int *result = new int[n];
for(int i=1;i<=n;i++)
{
result[i] = 1;
for(int j=i-1;j>=1;j--)
{
result[j] = result[j-1]+result[j];
}
result[0] = 1;
}
cout<<result[k]<<endl;
return 0;
}