22    using size_type = std::uint64_t;
 
   23    using block_type = std::uint64_t;
 
   24    static constexpr size_type bits_per_block =
 
   25        std::numeric_limits<block_type>::digits;
 
   27    dynamic_bitset() = 
default;
 
   33    explicit dynamic_bitset(size_type value) {
 
   36            m_blocks.resize(1, 0);
 
   39            m_num_bits = std::numeric_limits<size_type>::digits - clzll(value);
 
   40            m_blocks.resize((m_num_bits + bits_per_block - 1) / bits_per_block);
 
   46    size_type size()
 const {
 
   51        std::fill(m_blocks.begin(), m_blocks.end(), 0);
 
   54    void resize(size_type nbits) {
 
   56        m_blocks.resize((nbits + bits_per_block - 1) / bits_per_block);
 
   60    dynamic_bitset& masked_and_not(dynamic_bitset& exclude_mask) {
 
   61        if (exclude_mask.size() > size()) {
 
   62            resize(exclude_mask.size());
 
   63        } 
else if (size() > exclude_mask.size()) {
 
   64            exclude_mask.resize(size());
 
   67        for (size_type i = 0; i < m_blocks.size(); ++i) {
 
   68            m_blocks[i] &= ~exclude_mask.m_blocks[i];
 
   75    dynamic_bitset& operator&=(
const dynamic_bitset& rhs) {
 
   79        size_type min_blocks = (m_blocks.size() < rhs.m_blocks.size())
 
   81            : rhs.m_blocks.size();
 
   83        for (size_type i = 0; i < min_blocks; ++i) {
 
   84            m_blocks[i] &= rhs.m_blocks[i];
 
   87        if (m_blocks.size() > rhs.m_blocks.size()) {
 
   88            std::fill(m_blocks.begin() + min_blocks, m_blocks.end(), 0);
 
   95    dynamic_bitset& operator|=(
const dynamic_bitset& rhs) {
 
   96        if (rhs.m_num_bits > m_num_bits) {
 
   97            resize(rhs.m_num_bits);
 
   99        for (size_type i = 0; i < rhs.m_blocks.size(); ++i) {
 
  100            m_blocks[i] |= rhs.m_blocks[i];
 
  107    dynamic_bitset& operator^=(
const dynamic_bitset& rhs) {
 
  108        if (rhs.m_num_bits > m_num_bits) {
 
  109            resize(rhs.m_num_bits);
 
  111        for (size_type i = 0; i < rhs.m_blocks.size(); ++i) {
 
  112            m_blocks[i] ^= rhs.m_blocks[i];
 
  119    dynamic_bitset operator~()
 const {
 
  120        dynamic_bitset result(*
this);
 
  121        for (
auto& block : result.m_blocks) {
 
  124        result.zero_unused_bits();
 
  129    dynamic_bitset& operator<<=(size_type shift) {
 
  130        if (shift >= m_num_bits) {
 
  132            std::fill(m_blocks.begin(), m_blocks.end(), 0);
 
  136        size_type block_shift = shift / bits_per_block;
 
  137        size_type bit_shift = shift % bits_per_block;
 
  138        size_type inv_bit_shift = bits_per_block - bit_shift;
 
  140        if (block_shift != 0) {
 
  141            for (size_type i = m_blocks.size(); i-- > block_shift;) {
 
  142                m_blocks[i] = m_blocks[i - block_shift];
 
  144            std::fill(m_blocks.begin(), m_blocks.begin() + block_shift, 0);
 
  147        if (bit_shift != 0) {
 
  148            block_type carry = 0;
 
  149            for (size_type i = block_shift; i < m_blocks.size(); ++i) {
 
  150                block_type temp = m_blocks[i];
 
  151                m_blocks[i] = (temp << bit_shift) | carry;
 
  152                carry = temp >> inv_bit_shift;
 
  160    dynamic_bitset& operator>>=(size_type shift) {
 
  161        if (shift >= m_num_bits) {
 
  163            std::fill(m_blocks.begin(), m_blocks.end(), 0);
 
  167        size_type block_shift = shift / bits_per_block;
 
  168        size_type bit_shift = shift % bits_per_block;
 
  169        size_type inv_bit_shift = bits_per_block - bit_shift;
 
  171        if (block_shift != 0) {
 
  172            for (size_type i = 0; i < m_blocks.size() - block_shift; ++i) {
 
  173                m_blocks[i] = m_blocks[i + block_shift];
 
  175            std::fill(m_blocks.end() - block_shift, m_blocks.end(), 0);
 
  178        if (bit_shift != 0) {
 
  179            block_type carry = 0;
 
  180            for (size_type i = m_blocks.size(); i-- > 0;) {
 
  181                block_type temp = m_blocks[i];
 
  182                m_blocks[i] = (temp >> bit_shift) | carry;
 
  183                carry = temp << inv_bit_shift;
 
  191    friend dynamic_bitset
 
  192    operator&(dynamic_bitset lhs, 
const dynamic_bitset& rhs) {
 
  197    friend dynamic_bitset
 
  198    operator|(dynamic_bitset lhs, 
const dynamic_bitset& rhs) {
 
  203    friend dynamic_bitset
 
  204    operator^(dynamic_bitset lhs, 
const dynamic_bitset& rhs) {
 
  209    friend dynamic_bitset operator<<(dynamic_bitset lhs, size_type shift) {
 
  214    friend dynamic_bitset operator>>(dynamic_bitset lhs, size_type shift) {
 
  220    bool operator[](size_type pos)
 const {
 
  221        if (pos >= m_num_bits) {
 
  224        size_type block_index = pos / bits_per_block;
 
  225        size_type bit_index = pos % bits_per_block;
 
  226        return (m_blocks[block_index] & (block_type(1) << bit_index)) != 0;
 
  230    void set(size_type pos, 
bool value = 
true) {
 
  231        if (pos >= m_num_bits) {
 
  234        size_type block_index = pos / bits_per_block;
 
  235        size_type bit_index = pos % bits_per_block;
 
  237            m_blocks[block_index] |= (block_type(1) << bit_index);
 
  239            m_blocks[block_index] &= ~(block_type(1) << bit_index);
 
  244    void reset(size_type pos) {
 
  249    void flip(size_type pos) {
 
  250        if (pos >= m_num_bits) {
 
  253        size_type block_index = pos / bits_per_block;
 
  254        size_type bit_index = pos % bits_per_block;
 
  255        m_blocks[block_index] ^= (block_type(1) << bit_index);
 
  259    bool operator==(
const dynamic_bitset& rhs)
 const {
 
  260        if (m_num_bits != rhs.m_num_bits) {
 
  263        return m_blocks == rhs.m_blocks;
 
  266    bool operator!=(
const dynamic_bitset& rhs)
 const {
 
  267        return !(*
this == rhs);
 
  271    size_type count()
 const {
 
  273        for (
const auto& block : m_blocks) {
 
  274            cnt += popcount(block);
 
  281        for (
const auto& m_block : m_blocks) {
 
  294    bool contains(
const dynamic_bitset& other)
 const {
 
  296        for (
size_t i = 0; i < other.size(); ++i) {
 
  297            if (other.test(i) && !this->test(i)) {
 
  305    bool test(size_type pos)
 const {
 
  306        return operator[](pos);
 
  309    std::string to_string()
 const {
 
  310        std::string result(m_num_bits, 
'0');  
 
  312        for (size_type i = 0; i < m_num_bits; ++i) {
 
  314                result[m_num_bits - 1 - i] = 
'1';  
 
  321    std::vector<block_type> m_blocks;
 
  322    size_t m_num_bits {0};
 
  324    void zero_unused_bits() {
 
  327        size_type unused_bits = bits_per_block - (m_num_bits % bits_per_block);
 
  328        if (unused_bits != bits_per_block) {
 
  329            m_blocks.back() &= (block_type(~0) >> unused_bits);
 
  334    inline static int clzll(
unsigned long long value) {
 
  336        return _BitScanReverse64(&index, value) ? (63 - index) : 64;
 
  339    inline static int clzll(
unsigned long long value) {
 
  340        return value == 0 ? 64 : __builtin_clzll(value);
 
  344    static size_type popcount(block_type x) {
 
  345#if defined(__GNUC__) || defined(__clang__) 
  346        if constexpr (
sizeof(block_type) <= 
sizeof(
unsigned int))
 
  347            return __builtin_popcount(x);
 
  348        else if constexpr (
sizeof(block_type) <= 
sizeof(
unsigned long))
 
  349            return __builtin_popcountl(x);
 
  350        else if constexpr (
sizeof(block_type) <= 
sizeof(
unsigned long long))
 
  351            return __builtin_popcountll(x);
 
  361#elif defined(_MSC_VER) 
  362        if constexpr (
sizeof(block_type) == 
sizeof(
unsigned int))
 
  363            return __popcnt(
static_cast<unsigned int>(x));
 
  364        else if constexpr (
sizeof(block_type) == 
sizeof(
unsigned long long))
 
  365            return __popcnt64(
static_cast<unsigned long long>(x));
 
  385    friend struct std::hash<dynamic_bitset>;