组合

在组合数学，一个集的元素的组合（Combination）是一个子集。"S"的一个"k"-组合是"S"的一个有k个元素的子集。若两个子集的元素完全相同并顺序相异，它仍视为同一个组合，这是组合和排列不同之处。
表示方式.
从 n 个不同元素中取出 k 个元素的所有不同组合的个数，叫做从 n 个不同元素中取出 k 个元素的组合数，记做：formula_1、formula_2、formula_3、formula_4（英语）、formula_5（法语、罗马尼亚语、俄语、汉语、波兰语）。
理论与公式.
从formula_6个元素中取出formula_7个元素，formula_7个元素的组合数量为：
以六合彩为例。在六合彩中从49颗球中取出6颗球的组合数量为：
重复组合理论与公式.
从formula_6个元素中取出formula_7个元素，formula_7个元素可以重复出现，这组合数量为：
以取色球为例，每种颜色的球有无限多颗，从8种色球中取出5颗球，好比是在5颗球间画上分隔号“|”代表球色的分布情形(隔板法)。例如第1种色球取1颗，第2种色球取2颗，第3种色球取2颗可以表示成：
可以理解为8类球每类取多少个，一起构成5个球。我们把5个球排成一排，用7个分隔线去隔开。如上图，表示含义：第1根线前表示第一类球取的个数，第1根和第2根线表示第二类球取的个数...第6第7根线前表示第七类球的个数，第7根后表示第八类球的个数。亦即问题是从(5+8-1)个位置中挑选出(8-1)个位置摆分隔号，这组合数量为：
因为组合数量公式特性，重复组合转换成组合有另一种公式为：
另外formula_17也可以记为formula_18或formula_19
取值范围的扩充.
在formula_22的定义中，由于它有意义的范围必须是满足条件formula_23，所以其他范围必须另外定义，我们有:
演算范例.
组合 C.
回圈法.
<syntaxhighlight lang="cpp">
/** This is C++ code. **/
/** Comb Example **/
using namespace std;
bool next_comb(vector<int>& comb, const int n, const int k) {
int main() {
</syntaxhighlight>
递回法.
<syntaxhighlight lang="cpp">
using namespace std;
namespace comb {
int n, k;
int arr;
int count;
bool arrsame(int site) {
 if (site > 0 && arr- 1 >= arr)
 return 0;
 return 1;
inline void arrprint() {
 for (int i = 0; i < k; i++)
 printf("%3d", arr);
 puts("");
 count++;
void calculate(int now) {
 if (now == k) {
 arrprint();
 return;
 for (int i = 0; i < n; i++) {
 arr = i;
 if (arrsame(now)) {
 calculate(now + 1);
inline void run(int nn, int kk) {
 n = nn, k = kk;
 count = 0;
 if (k < 12 && n >= k && k > 0)
 calculate(0);
 if (count)
 printf("\n%d combination.\n\n", count);
 else
 puts("Input error!");
int main() {
 int n, k;
 while (scanf("%d%d", &n, &k) != EOF) {
 comb::run(n, k);
 fflush(stdout);
 return 0;
</syntaxhighlight>
重复组合 H.
回圈法.
<syntaxhighlight lang="cpp">
/** This is C++ code. **/
/** ReComb Example **/
using namespace std;
bool next_re_comb(int* recomb, const int n, const int k) {
 int i = k - 1;
 do
 recomb++;
 while (recomb > n - 1 && i--);
 if (recomb > n - 1)
 return 0;
 while (++i < k)
 recomb= recomb[i - 1;
 return 1;
int main() {
 int n, k;
 cout Â« "recomb(n,k):" Â« endl;
 cin Â» n Â» k;
 if (n <= 0 || k <= 0)
 return 0;
 int* recomb = new int;
 for (int i = 0; i < k; i++)
 recomb = 0;
 do
 for (int i = 0; i < k; cout Â« ((++i < k) ? ',' : '\n'))
 cout Â« recomb + 1;
 while (next_re_comb(recomb, n, k));
 delete[] recomb;
 return 0;
</syntaxhighlight>
递回法.
<syntaxhighlight lang="cpp">
using namespace std;
namespace re_comb {
int n, k;
int arr;
int count;
bool arrsame(int site) {
 if (site > 0 && arr- 1 > arr)
 return 0;
 return 1;
inline void arrprint() {
 for (int i = 0; i < k; i++)
 printf("%3d", arr);
 puts("");
 count++;
void calculate(int now) {
 if (now == k) {
 arrprint();
 return;
 for (int i = 0; i < n; i++) {
 arr = i;
 if (arrsame(now)) {
 calculate(now + 1);
inline void run(int nn, int kk) {
 n = nn, k = kk;
 count = 0;
 if (k < 12 && k > 0)
 calculate(0);
 if (count)
 printf("\n%d combination.\n\n", count);
 else
 puts("Input error!");
int main() {
 int n, k;
 while (scanf("%d%d", &n, &k) != EOF) {
 re_comb::run(n, k);
 fflush(stdout);
 return 0;
</syntaxhighlight>
推广.
组合数可以推广到多分类的情形 ，我们将n个物品分为m份，每份的个数分别为:formula_25个，那么，总的分类数为