• P1157组合数的输出 题解


    组合数的输出

    题目传递门

    (n=5)为例,那么原集合就是{(1,2,3,4,5)}
    按照每个数字是否存在于子集合中可能有:
    {(0,0,0,0,0)} ---->{}
    {(0,0,0,0,1)} ---->{(5)}
    {(0,0,0,1,0)} ---->{(4)}
    {(0,0,0,1,1)} ---->{(4,5)}
    {(0,0,1,0,0)} ---->{(3)}
    ...

    这样的二进制形式,就可以模拟出所有的子集选择情况。

    这些二进制,还是可以从0,一直到 31的, 也就是说,我们可以用循环从0遍历到31,就成功模拟了这32种情况,对应着32种子集合。假设我们写出了如下的代码:

    for(int i=0;i<31;i++){
        ...
    }
    

    由于数字是从(0)(31),所以第一个考查的是0,第二个考查的是1,最后一个考查的是31,对应二进制就是:

    数字 对应的二进制 对应的集合
    (0) 0 0 0 0 0 {} 空集合
    (1) 0 0 0 0 1 {5}
    (2) 0 0 0 1 0 {4}
    (3) 0 0 0 1 1 {4,5}
    (4) 0 0 1 0 0 {3}
    (5) 0 0 1 0 1 {3,5}
    (6) 0 0 1 1 0 {3,4}
    (7) 0 0 1 1 1 {3,4,5}
    (8) 0 1 0 0 0 {2}
    (9) 0 1 0 0 1 {2,5}
    (10) 0 1 0 1 0 {2,4}
    (11) 0 1 0 1 1 {2,4,5}
    (12) 0 1 1 0 0 {2,3}
    (13) 0 1 1 0 1 {2,3,5}
    (14) 0 1 1 1 0 {2,3,4}
    (15) 0 1 1 1 1 {2,3,4,5}
    (16) 1 0 0 0 0 {1}
    (17) 1 0 0 0 1 {1,5}
    (18) 1 0 0 1 0 {1,4}
    (19) 1 0 0 1 1 {1,4,5}
    (20) 1 0 1 0 0 {1,3}
    (21) 1 0 1 0 1 {1,3,5}
    (22) 1 0 1 1 0 {1,3,4}
    (23) 1 0 1 1 1 {1,3,4,5}
    (24) 1 1 0 0 0 {1,2}
    (25) 1 1 0 0 1 {1,2,5}
    (26) 1 1 0 1 0 {1,2,4}
    (27) 1 1 0 1 1 {1,2,4,5}
    (28) 1 1 1 0 0 {1,2,3}
    (29) 1 1 1 0 1 {1,2,3,5}
    (30) 1 1 1 1 0 {1,2,3,4}
    (31) 1 1 1 1 1 {1,2,3,4,5}

    由于例子是(r=3),所以:

    数字 对应的二进制 对应的集合
    (7) 0 0 1 1 1 {3,4,5}
    (11) 0 1 0 1 1 {2,4,5}
    (13) 0 1 1 0 1 {2,3,5}
    (14) 0 1 1 1 0 {2,3,4}
    (19) 1 0 0 1 1 {1,4,5}
    (21) 1 0 1 0 1 {1,3,5}
    (22) 1 0 1 1 0 {1,3,4}
    (25) 1 1 0 0 1 {1,2,5}
    (26) 1 1 0 1 0 {1,2,4}
    (28) 1 1 1 0 0 {1,2,3}
    #include <bits/stdc++.h>
    
    using namespace std;
    const int N = 30;
    int a[N];
    
    int main() {
        int n, r;
        cin >> n >> r;
    
        //如果是正序
        for (int S = 0; S <= (1 << n) - 1; S++) {
            //每次循环需要清0
            memset(a, 0, sizeof a);
            int cnt = 0;
    
            for (int i = n - 1; i >= 0; i--)    //遍历S的每一个二进制位(从高位到低位)
                if (S & (1 << i)) a[cnt++] = i; //记录S的哪些数位不为0
    
            //只需要r位
            if (r == cnt) {
                cout << S << "    {";
                /*
                 数组内容4,对应着数字1
                 数组内容3,对应着数字2
                 数组内容2,对应着数字3
                 数组内容1,对应着数字4
                 数组内容0,对应着数字5
                 就是一个两者相加等于n的关系。
                 */
                for (int i = 0; i < cnt; i++) cout << n - a[i] << " ";
                cout << "}
    ";
            }
        }
        return 0;
    }
    

    大数在前,才能保证 10110 早于 10101.修改一下:

    #include <bits/stdc++.h>
    
    using namespace std;
    const int N = 30;
    int a[N];
    
    int main() {
        int n, r;
        cin >> n >> r;
    
        //大数在前,才能保证 10110 早于 10101
        for (int S = (1 << n) - 1; S >= 0; S--) {
            //每次循环需要清0
            memset(a, 0, sizeof a);
            int cnt = 0;
    
            for (int i = n - 1; i >= 0; i--)    //遍历S的每一个二进制位(从高位到低位)
                if (S & (1 << i)) a[cnt++] = i; //记录S的哪些数位不为0
    
            //只需要r位
            if (r == cnt) {
                printf("%3d", S);
                cout << "    { ";
                /*
                 数组内容4,对应着数字1
                 数组内容3,对应着数字2
                 数组内容2,对应着数字3
                 数组内容1,对应着数字4
                 数组内容0,对应着数字5
                 就是一个两者相加等于n的关系。
                 */
                for (int i = 0; i < cnt; i++) cout << n - a[i] << " ";
                cout << "}
    ";
            }
        }
        return 0;
    }
    
  • 相关阅读:
    QProgressBar的使用例子
    kube框架结构-一个小型响应式CSS框架
    窗口类型(Widget, Window, Dialog, Desktop, SubWindow等等)
    Qt 之 设置窗口边框的圆角(使用QSS和PaintEvent两种方法)
    十大开源游戏引擎深入比较
    一种通用查询语言的定义与实践
    EF分页问题探讨之 OrderBy
    手把手教你做关键词匹配项目
    git
    Extension+NVelocity
  • 原文地址:https://www.cnblogs.com/littlehb/p/15005039.html
Copyright © 2020-2023  润新知