简体   繁体   English

使用 std::bitset 计算有限集的子集

[英]Using std::bitset to count subsets of a finite set

I would like to check how many subsets S of the set [1, ..., 15] there are so that it is impossible to choose two elements from S such that their sum is a multiple of 3.我想检查集合 [1, ..., 15] 的子集 S 有多少个,因此不可能从 S 中选择两个元素,使得它们的总和是 3 的倍数。

The algorithm to check this is as follows: there is a natural bijection between the subsets of [1, ..., 15] and the strings of length 15 with two characters (assume the two characters are '0' and '1' to fix a convention), where the character '0' in position i means that the integer i is not in the subset, while the character '1' in position i means that the integer i is in the subset.检查这一点的算法如下:在 [1, ..., 15] 的子集和具有两个字符的长度为 15 的字符串之间存在自然双射(假设这两个字符是 '0' 和 '1' 到固定约定),其中位置 i 的字符“0”表示整数 i 不在子集中,而位置 i 的字符“1”表示整数 i 在子集中。 For example, the string "111001000000000" is associated to the subset {1, 2, 3, 6}.例如,字符串“111001000000000”与子集 {1, 2, 3, 6} 相关联。 This subset does not fulfill the constraint described above.该子集不满足上述约束。

I wrote a C++ code to generate all such strings, convert them to a vector of ints between 1 and 15, and check for all couples in this set if there is one whose sum is a multiple of 3.我编写了一个 C++ 代码来生成所有这些字符串,将它们转换为 1 到 15 之间的整数向量,并检查该集合中的所有对是否存在总和是 3 的倍数。

This is the code:这是代码:

#include <algorithm>
#include <bitset>
#include <cmath>
#include <iostream>
#include <vector>


bool check(const std::vector<int>& dset) {
    if (dset.size() == 1) {
        if (dset[0] % 3 == 0) { return false; }
    }
    for (size_t i = 0; i < dset.size() - 1; ++i) {
        auto a = dset[i];
        for (size_t j = i + 1; j < dset.size(); ++j) {
            auto b = dset[j];
            if ((a + b) % 3 == 0) { return false; }
        }
    }
    return true;
}


int main() {
    const int N = 15;  // We consider subsets of [1, ..., N].
    int approved = 1;  // We automatically approve the empty set.
    std::bitset<N> set;
    for (int n = 1; n < std::pow(2, N); ++n) {
        set = std::bitset<N>(n);
        std::vector<int> dset(set.count());
        size_t j = 0;
        for (int i = 1; i <= N; ++i) {
            if (set[i - 1]) {
                dset[j++] = i;
            }
        }
        // Sweep through all couples in dset.
        if (check(dset)) {
            ++approved;
        }
    }
    std::cout << approved << " out of " << std::pow(2, N) << std::endl;
}

The problem is that my code returns 373, which is the wrong answer (the correct one should be 378).问题是我的代码返回 373,这是错误的答案(正确的应该是 378)。 I guess I am doing something wrong here, but I cannot find the error in my code.我想我在这里做错了什么,但我在我的代码中找不到错误。

In check() function you don't need to check for dset size being 1 , since it is taken care below in the for loop from index i = 0 till valid size.check()函数中,您不需要检查dset大小是否为1 ,因为它在下面的for循环中从索引i = 0到有效大小进行了处理。 Remove below if statement which should result valid number whose sum is multiple of 3 :删除下面的if语句,它应该产生总和是3倍数的有效数字:

if (dset.size() == 1) {
    if (dset[0] % 3 == 0) { return false; }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM