组合的输出

GitHub跳转原题关系图返回列表

用 itertools.combinations 按字典序枚举 1 到 n 中选 r 个数,并用格式化字符串控制每个数宽度为 3。

OJ: luogu

题目 ID: P1157

难度:入门

标签:枚举组合python

日期: 2026-07-15 21:30

题意

1..n 中选出 r 个数,按字典序输出所有组合。每个数字输出时占 3 个字符宽度。

思路

组合要求:

  • 每行内部数字递增;
  • 所有行按字典序排列;
  • 不关心选择顺序,只关心选出的集合。

itertools.combinations(range(1, n + 1), r) 正好满足这些条件。它会按照输入序列的顺序生成组合,所以输出顺序就是题目要求的字典序。

每个数占 3 个字符,可以写成:

python
f"{number:3d}"

再把一行中的字段拼接起来输出。

Python 知识

  • combinations(range(1, n + 1), r) 表示从 1..n 中选 r 个。
  • f"{number:3d}" 是格式化字符串,含义是整数右对齐,占 3 个字符宽度。
  • "".join(...) 把一行的多个格式化字段拼成一个字符串。

参考笔记:

  • /home/rainboy/mycode/hugo-blog/content/program_language/python/brute_force_validation.md
  • /home/rainboy/mycode/hugo-blog/content/program_language/python/itertools_recipes.md
  • /home/rainboy/mycode/hugo-blog/content/program_language/python/input_output_and_strings.md

代码

python
from itertools import combinations

n, r = map(int, input().split())

for chosen in combinations(range(1, n + 1), r):
    print("".join(f"{number:3d}" for number in chosen))
cpp
/**
 * Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
 * rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
 * rainboy的学习导航网站: https://idx.roj.ac.cn
 * create_at: 2026-07-27 00:00
 * update_at: 2026-07-27 00:00
 */
#include <bits/stdc++.h>
using namespace std;

int n, r;
int choose[25];

void dfs(int dep, int start) {
    if (dep == r) {
        for (int i = 0; i < r; i++)
            cout << setw(3) << choose[i];
        cout << endl;
        return;
    }
    for (int i = start; i <= n; i++) {
        choose[dep] = i;
        dfs(dep + 1, i + 1);
    }
}

int main() {
    cin >> n >> r;
    dfs(0, 1);
    return 0;
}

复杂度

会输出 (nr)\binom{n}{r} 行,每行有 r 个数。时间复杂度为 O(r(nr))O(r\binom{n}{r}),空间复杂度为 O(r)O(r)

总结

这题的重点不是手写递归,而是学会把“按字典序输出组合”直接交给 itertools.combinations