#line 1 "data_structure/test/dynamic_bitset.yuki3060.test.cpp" #define PROBLEM "https://yukicoder.me/problems/no/3060" #line 2 "data_structure/dynamic_bitset.hpp" #include #include #include struct dynamic_bitset { using ull = unsigned long long; static constexpr int W = 64; int n = 0; // number of bits int m = 0; // number of 64-bit blocks std::vector a; // blocks dynamic_bitset() = default; explicit dynamic_bitset(int n_, bool init_one = false) { reset_size(n_, init_one); } explicit dynamic_bitset(const std::string &s) : dynamic_bitset(int(s.size())) { for (int i = 0; i < n; ++i) set(i, s[i] == '1'); } void reset_size(int n_, bool init_one = false) { n = n_; m = (n + W - 1) / W; a.assign(m, init_one ? ~0ULL : 0ULL); trim(); } int size() const { return n; } // ---- low-level helpers ---- ull last_mask() const { int r = n & (W - 1); if (r == 0) return ~0ULL; return (r == 64 ? ~0ULL : ((1ULL << r) - 1ULL)); } void trim() { if (m == 0) return; a.back() &= last_mask(); } static inline int ctz64(ull x) { return __builtin_ctzll(x); } static inline int clz64(ull x) { return __builtin_clzll(x); } static inline int msb_index64(ull x) { return 63 - clz64(x); } // x != 0 // ---- basic bit ops ---- bool test(int i) const { return (a[i >> 6] >> (i & 63)) & 1ULL; } void set(int i) { a[i >> 6] |= (1ULL << (i & 63)); } void reset(int i) { a[i >> 6] &= ~(1ULL << (i & 63)); } void flip(int i) { a[i >> 6] ^= (1ULL << (i & 63)); } void set(int i, bool v) { v ? set(i) : reset(i); } void reset_all() { std::fill(a.begin(), a.end(), 0ULL); } void set_all() { std::fill(a.begin(), a.end(), ~0ULL); trim(); } void flip_all() { for (auto &x : a) x = ~x; trim(); } // count (optional but handy) long long popcount() const { long long s = 0; for (ull x : a) s += __builtin_popcountll(x); return s; } long long count() const { return popcount(); } // ---- bitwise ops ---- // ---- any / none ---- bool any() const { for (ull x : a) if (x) return true; return false; } bool none() const { return !any(); } // ---- bitwise assign ops ---- dynamic_bitset &operator^=(const dynamic_bitset &o) { // assume same size in competitive programming usage for (int i = 0; i < m; i++) a[i] ^= o.a[i]; trim(); return *this; } dynamic_bitset &operator|=(const dynamic_bitset &o) { for (int i = 0; i < m; i++) a[i] |= o.a[i]; trim(); return *this; } dynamic_bitset &operator&=(const dynamic_bitset &o) { for (int i = 0; i < m; i++) a[i] &= o.a[i]; trim(); return *this; } friend dynamic_bitset operator^(dynamic_bitset l, const dynamic_bitset &r) { l ^= r; return l; } friend dynamic_bitset operator|(dynamic_bitset l, const dynamic_bitset &r) { l |= r; return l; } friend dynamic_bitset operator&(dynamic_bitset l, const dynamic_bitset &r) { l &= r; return l; } bool operator==(const dynamic_bitset &o) const { return n == o.n && a == o.a; } bool operator!=(const dynamic_bitset &o) const { return !(*this == o); } dynamic_bitset operator~() const { dynamic_bitset r = *this; for (auto &x : r.a) x = ~x; r.trim(); return r; } // ---- shifts ---- dynamic_bitset &operator<<=(int k) { if (k <= 0 || n == 0) return *this; if (k >= n) { reset_all(); return *this; } int ws = k >> 6; int bs = k & 63; if (ws) { for (int i = m - 1; i >= 0; --i) { ull v = (i - ws >= 0) ? a[i - ws] : 0ULL; a[i] = v; } } if (bs) { for (int i = m - 1; i >= 0; --i) { ull hi = a[i] << bs; ull lo = (i ? (a[i - 1] >> (64 - bs)) : 0ULL); a[i] = hi | lo; } } // zero-fill lower words introduced by ws shift if (ws) { for (int i = 0; i < ws && i < m; ++i) a[i] = 0ULL; } trim(); return *this; } dynamic_bitset &operator>>=(int k) { if (k <= 0 || n == 0) return *this; if (k >= n) { reset_all(); return *this; } int ws = k >> 6; int bs = k & 63; if (ws) { for (int i = 0; i < m; ++i) { ull v = (i + ws < m) ? a[i + ws] : 0ULL; a[i] = v; } } if (bs) { for (int i = 0; i < m; ++i) { ull lo = a[i] >> bs; ull hi = (i + 1 < m ? (a[i + 1] << (64 - bs)) : 0ULL); a[i] = lo | hi; } } // zero-fill upper words introduced by ws shift if (ws) { for (int i = m - ws; i < m; ++i) if (0 <= i && i < m) a[i] = 0ULL; } trim(); return *this; } friend dynamic_bitset operator<<(dynamic_bitset b, int k) { b <<= k; return b; } friend dynamic_bitset operator>>(dynamic_bitset b, int k) { b >>= k; return b; } // ---- find set bits ---- // returns smallest i with bit=1, or -1 int first() const { for (int i = 0; i < m; ++i) { ull x = a[i]; if (x) return (i << 6) + ctz64(x); } return -1; } // returns smallest j > i with bit=1, or -1 int next(int i) const { if (n == 0) return -1; int j = i + 1; if (j <= 0) return first(); if (j >= n) return -1; int b = j >> 6; int off = j & 63; // mask out bits < off ull x = a[b] & (~0ULL << off); if (x) return (b << 6) + ctz64(x); for (int bb = b + 1; bb < m; ++bb) { ull y = a[bb]; if (y) return (bb << 6) + ctz64(y); } return -1; } // returns largest i with bit=1, or -1 int last() const { for (int i = m - 1; i >= 0; --i) { ull x = a[i]; if (i == m - 1) x &= last_mask(); if (x) return (i << 6) + msb_index64(x); } return -1; } // returns largest j < i with bit=1, or -1 int prev(int i) const { if (n == 0) return -1; int j = i - 1; if (j < 0) return -1; if (j >= n) return last(); int b = j >> 6; int off = j & 63; ull mask = (off == 63) ? ~0ULL : ((1ULL << (off + 1)) - 1ULL); ull x = a[b] & mask; if (x) return (b << 6) + msb_index64(x); for (int bb = b - 1; bb >= 0; --bb) { ull y = a[bb]; if (y) return (bb << 6) + msb_index64(y); } return -1; } }; #line 4 "data_structure/test/dynamic_bitset.yuki3060.test.cpp" #include #line 6 "data_structure/test/dynamic_bitset.yuki3060.test.cpp" using namespace std; int main() { cin.tie(nullptr), ios::sync_with_stdio(false); int H, W; cin >> H >> W; using BS = dynamic_bitset; vector A(H); for (int i = 0; i < H; ++i) { string s; cin >> s; A.at(i) = BS(s); } sort(A.begin(), A.end(), [&](const BS &l, const BS &r) { return l.count() < r.count(); }); vector dp(H + 1); for (int i = 0; i < H; ++i) { dp[i + 1] = max(dp[i + 1], 1); for (int j = 0; j < i; ++j) { if ((A.at(i) & A.at(j)) == A.at(j)) dp[i + 1] = max(dp[i + 1], dp[j + 1] + 1); } } cout << H - *max_element(dp.begin(), dp.end()) << '\n'; }