使用std :: bitset对有限集的子集进行计数

时间:2019-11-27 11:23:33

标签: c++ bitset std-bitset

我想检查集合[1,...,15]中有多少个子集S 使得不可能从S中选择两个元素 这样它们的总和就是3的倍数。

检查此算法的算法如下:之间存在自然双射 [1,...,15]的子集和带有两个字符的长度为15的字符串(假定 这两个字符分别是“ 0”和“ 1”(以符合约定),其中位置i处的字符“ 0”表示整数i不在子集中,而位置i处的字符“ 1”表示整数我在子集中。 例如,字符串“ 111001000000000”与子集{1、2、3、6}相关联。此子集不满足上述约束。

我写了一个C ++代码来生成所有这样的字符串,并将它们转换为 介于1到15之间的整数,并检查该集合中是否有所有对 其总和是3的倍数。

这是代码:

#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;
}

问题是我的代码返回373,这是错误的答案(正确的答案应该是378)。 我想我在这里做错了,但是我找不到我的代码中的错误。

1 个答案:

答案 0 :(得分:0)

check()函数中,您无需检查dset的大小是否为1,因为在下面的for循环中,从索引{{1 }}直到有效大小。删除下面的i = 0语句,该语句应得出有效数字,其总和是if的倍数:

3