2429: 【普及-】【P1157】组合的输出

内存限制:128 MB 时间限制:1.000 S
评测方式:文本比较 命题人:
提交:8 解决:6

题目描述

排列与组合是常用的数学方法,其中组合就是从 lns="http://www.w3.org/1998/Math/MathML"> 个元素中抽出 lns="http://www.w3.org/1998/Math/MathML"> 个元素(不分顺序且 lns="http://www.w3.org/1998/Math/MathML">),我们可以简单地将 lns="http://www.w3.org/1998/Math/MathML"> 个元素理解为自然数 lns="http://www.w3.org/1998/Math/MathML">1,2,,,从中任取 lns="http://www.w3.org/1998/Math/MathML"> 个数。

现要求你输出所有组合。

例如 lns="http://www.w3.org/1998/Math/MathML">=5,=3,所有组合为:

lns="http://www.w3.org/1998/Math/MathML">123,124,125,134,135,145,234,235,245,345

输入

一行两个自然数 lns="http://www.w3.org/1998/Math/MathML">,(1<<21,0)

输出

所有的组合,每一个组合占一行且其中的元素按由小到大的顺序排列,每个元素占三个字符的位置,所有的组合也按字典顺序。

注意哦!输出时,每个数字需要 lns="http://www.w3.org/1998/Math/MathML">3 个场宽。以 C++ 为例,你可以使用下列代码:

cout << setw(3) << x; 

输出占 lns="http://www.w3.org/1998/Math/MathML">3 个场宽的数 lns="http://www.w3.org/1998/Math/MathML">。注意你需要头文件 iomanip

样例输入 复制

5 3 

样例输出 复制

  1  2  3
  1  2  4
  1  2  5
  1  3  4
  1  3  5
  1  4  5
  2  3  4
  2  3  5
  2  4  5
  3  4  5

提示

#include<bits/stdc++.h>
using namespace std;
int a[30];
int main(){
    int n,r;
    cin>>n>>r;
    /*
    从全集枚举到0,从高位到低位分别表示元素1到n,
    就可以让1尽量出现在靠前(左)的位置,
    比如让10110(代表‘134’)早于10101(代表‘135’)出现,符合字典序要求
    */
    for (int S=(1<<n)-1;S>=0;S--) { //从全集枚举到0
	    int cnt=0;
		for (int i=0;i<n;i++)
		    if (S&(1<<i))
			    a[cnt++]=n-i;  //分离记录每一位
	            //如10110代表‘134’, a[0]=4,a[1]=3,a[2]=1
		if (cnt==r) {
		    for (int i=r-1;i>=0;i--)
			    printf("%3d",a[i]);  
		    puts(""); 
		} 
	}
	return 0;
}