#define SINGLE_TESTCASE // #define MULTI_TESTCASE // #define AOJ_TESTCASE // #define FAST_IO // #define FAST_CIO #define INTERACTIVE #define INF 4'000'000'000'000'000'037LL #define EPS 1e-11 // https://github.com/miscalculation53/library/tree/wip/template/template_all.hpp // https://github.com/miscalculation53/library/tree/wip/template/template_all_but_modint.hpp // https://github.com/miscalculation53/library/tree/wip/template/template_types.hpp #include using namespace std; using ll = long long; using uint = unsigned int; using ull = unsigned long long; using pll = pair; #define vc vector template using vvc = vc>; using vstr = vc; using i128 = __int128_t; using u128 = __uint128_t; i128 stoi128(const string &s) { const bool neg = s.front() == '-'; u128 res = 0; for (int i = neg; i < (int)s.size(); i++) res = 10 * res + s[i] - '0'; if (neg) return -i128(res - 1) - 1; return i128(res); } string i128tos(i128 x) { if (x == 0) return "0"; string sign = "", res = ""; u128 ux; if (x < 0) ux = u128(-(x + 1)) + 1, sign = "-"; else ux = x; while (ux > 0) { res += '0' + ux % 10; ux /= 10; } reverse(res.begin(), res.end()); return sign + res; } istream &operator>>(istream &is, i128 &a) { string s; is >> s; a = stoi128(s); return is; } ostream &operator<<(ostream &os, const i128 &a) { os << i128tos(a); return os; } #define cauto const auto // https://github.com/miscalculation53/library/tree/wip/template/template_rep.hpp #define overload4(_1,_2,_3,_4,name,...) name #define rep1(i,n) for (ll i = 0, nnnnn = ll(n); i < nnnnn; i++) #define rep2(i,l,r) for (ll i = ll(l), rrrrr = ll(r); i < rrrrr; i++) #define rep3(i,l,r,d) for (ll i = ll(l), rrrrr = ll(r), ddddd = ll(d); ddddd > 0 ? i < rrrrr : i > rrrrr; i += d) #define rep(...) overload4(__VA_ARGS__, rep3, rep2, rep1)(__VA_ARGS__) #define repi1(i,n) for (int i = 0, nnnnn = int(n); i < nnnnn; i++) #define repi2(i,l,r) for (int i = int(l), rrrrr = int(r); i < rrrrr; i++) #define repi3(i,l,r,d) for (int i = int(l), rrrrr = int(r), ddddd = int(d); ddddd > 0 ? i < rrrrr : i > rrrrr; i += d) #define repi(...) overload4(__VA_ARGS__, repi3, repi2, repi1)(__VA_ARGS__) #define fe(...) for (auto __VA_ARGS__) #define fec(...) for (cauto &__VA_ARGS__) #define fem(...) for (auto &__VA_ARGS__) // https://github.com/miscalculation53/library/tree/wip/template/template_math.hpp // https://github.com/miscalculation53/library/tree/wip/utils/is_integral_ext.hpp template constexpr bool is_integral_ext = is_integral_v || is_same_v || is_same_v; template constexpr bool is_signed_ext = is_signed_v || is_same_v; template constexpr bool is_unsigned_ext = is_unsigned_v || is_same_v; // https://github.com/miscalculation53/library/tree/wip/utils/default_infty.hpp namespace default_infty_detail { template inline constexpr bool unsupported = false; } template inline bool chmin(T &a, U b) { return a > b ? a = b, true : false; } template && is_integral_ext>> inline constexpr T divfloor(U a, V b) { return T(a) / T(b) - (T(a) % T(b) && (T(a) ^ T(b)) < 0); } template && is_integral_ext>> inline constexpr T safemod(U a, V b) { return T(a) - T(b) * divfloor(a, b); } // https://github.com/miscalculation53/library/tree/wip/template/template_vector.hpp #define ALL(a) (a).begin(), (a).end() template inline T SZ(const V &x) { return x.size(); } #define eb emplace_back #define LMD(x,fx) ([&](const auto &x) { return fx; }) #define GEN_VEC(n,i,fi) (gen_vec(n, LMD(i, fi))) // https://github.com/miscalculation53/library/tree/wip/template/template_algo.hpp // https://github.com/miscalculation53/library/tree/wip/utils/resolved_infty.hpp // https://github.com/miscalculation53/library/tree/wip/utils/resolved_value.hpp template auto SUM(const V &v) { typename V::value_type s{}; fec(vi : v) s += vi; return s; } template auto MAX(const V &v) { return *max_element(ALL(v)); } template vvc top(const vvc &a) { if (a.empty()) return {}; const int n = a.size(), m = a[0].size(); vvc b(m, vc(n)); repi(i, n) { assert(SZ(a[i]) == m); repi(j, m) b[j][i] = a[i][j]; } return b; } vstr top(const vstr &a) { vvc a_(a.size()); repi(i, SZ(a)) a_[i] = {ALL(a[i])}; vvc b_ = top(a_); vstr b(b_.size()); repi(i, SZ(b)) b[i] = {ALL(b_[i])}; return b; } template struct has_e0 : false_type {}; template struct has_e0> : true_type {}; template inline constexpr bool has_e0_v = has_e0::value; namespace internal { } constexpr array DRULgrid = {{{1, 0}, {0, 1}, {-1, 0}, {0, -1}}}; constexpr array DRULplane = {{{0, -1}, {1, 0}, {0, 1}, {-1, 0}}}; // https://github.com/miscalculation53/library/tree/wip/template/template_binsearch.hpp template struct is_random_access_iterator { static constexpr bool value = is_same_v< typename iterator_traits::iterator_category, random_access_iterator_tag >; }; template constexpr bool is_random_access_iterator_v = is_random_access_iterator::value; #define DEFAULT_COMP ranges::less namespace internal { }; // https://github.com/miscalculation53/library/tree/wip/template/template_bit.hpp template inline constexpr ull MASK(T k) { return (1ULL << k) - 1ULL; } inline constexpr ll bit_width(ll x) { return std::bit_width((ull)x); } inline constexpr ll bit_floor(ll x) { return std::bit_floor((ull)x); } inline constexpr ll bit_ceil(ll x) { return std::bit_ceil((ull)x); } inline constexpr ll countr_zero(ll x) { assert(x != 0); return std::countr_zero((ull)x); } inline constexpr ll popcount(ll x) { return std::popcount((ull)x); } inline constexpr bool has_single_bit(ll x) { return std::has_single_bit((ull)x); } inline constexpr ull lsb_pos(ull x) { assert(x != 0); return countr_zero(x); } inline constexpr ull msb_pos(ull x) { assert(x != 0); return bit_width(x) - 1; } inline constexpr ull lsb_mask(ull x) { assert(x != 0); return x & -x; } inline constexpr ull msb_mask(ull x) { assert(x != 0); return bit_floor(x); } inline constexpr bool btest(ull x, uint k) { return (x >> k) & 1; } inline constexpr bool bsubset(ull x, ull y) { return (x & y) == x; } inline constexpr bool bsupset(ull x, ull y) { return (x & y) == y; } inline constexpr ull bsetminus(ull x, ull y) { return x & ~y; } // https://github.com/miscalculation53/library/tree/wip/template/template_inout.hpp // https://github.com/miscalculation53/library/tree/wip/template/template_dump.hpp // https://github.com/miscalculation53/library/tree/wip/template/template_dump_map.hpp #define CPP_DUMP_DEFINE_DATA(...) #define dump(...) #define local(...) #define oj(...) __VA_ARGS__ #define local_oj(a,b) (b) template istream &operator>>(istream &is, vc &a) { const size_t n = a.size(); for (size_t i = 0; i < n; i++) is >> a[i]; return is; } namespace internal { template void CIN(Ts &...a) { (cin >> ... >> a); } template void READnodump(Ts &...a) { CIN(a...); } template void READVECnodump(int n, vc &...v) { (v.resize(n), ...); READnodump(v...); } }; #define READ(...) internal::READnodump(__VA_ARGS__); dump(__VA_ARGS__) #define IN(T,...) T __VA_ARGS__; READ(__VA_ARGS__) #define CHAR(...) IN(char, __VA_ARGS__) #define INT(...) IN(int, __VA_ARGS__) #define LL(...) IN(ll, __VA_ARGS__) #define STR(...) IN(string, __VA_ARGS__) #define ARR(T,n,...) array __VA_ARGS__; READ(__VA_ARGS__) #define READVEC(...) internal::READVECnodump(__VA_ARGS__); dump(__VA_ARGS__) #define READVEC2(...) internal::READVEC2nodump(__VA_ARGS__); dump(__VA_ARGS__) #define VEC(T,n,...) vc __VA_ARGS__; READVEC(n, __VA_ARGS__) #define VEC2(T,n,m,...) vvc __VA_ARGS__; READVEC2(n, m, __VA_ARGS__) #define READJAG(...) internal::READJAGnodump(__VA_ARGS__); dump(__VA_ARGS__) #define JAG(T,n,...) vvc __VA_ARGS__; READJAG(n, __VA_ARGS__) #define ENDL endl template ostream &operator<<(ostream &os, const pair &p); template ostream &operator<<(ostream &os, const tuple &t); template ostream &operator<<(ostream &os, const array &a); template ostream &operator<<(ostream &os, const vc &v); namespace internal { template void COUTP(const Ts &...a) { if constexpr (sizeof...(Ts)) { int i = 0; ((cout << (i++ ? " " : "") << a), ...); } cout << ENDL; } }; #define WRITE internal::COUTW #define PRINT internal::COUTP #define PRINTEXIT(...) do { PRINT(__VA_ARGS__); exit(0); } while (false) #define PRINTRETURN(...) do { PRINT(__VA_ARGS__); return; } while (false) #define PRINTVEXIT(...) do { PRINTV(__VA_ARGS__); exit(0); } while (false) #define PRINTVRETURN(...) do { PRINTV(__VA_ARGS__); return; } while (false) namespace internal { }; namespace internal { }; #define UNZIP(vt,...) auto [__VA_ARGS__] = unzip(vt) #define ZIP(vt,...) auto vt = zip(tuple{__VA_ARGS__}) // https://github.com/miscalculation53/library/tree/wip/template/template_random.hpp mt19937_64 mt; bool randbool(double p) { assert(0 <= p && p <= 1); return bernoulli_distribution(p)(mt); } namespace internal { }; // https://github.com/miscalculation53/library/tree/wip/math/modint/template_modint.hpp // https://github.com/miscalculation53/library/tree/wip/math/modint/modint.hpp // https://github.com/miscalculation53/library/tree/wip/math/modint/modint_internal_static.hpp // https://github.com/miscalculation53/library/tree/wip/utils/larger_int.hpp namespace larger_int_detail { } template struct larger_int { private: static constexpr bool check(); static_assert(check()); public: using type = T; }; #define LARGER_INT(T,U) template <> struct larger_int { using type = U; }; LARGER_INT(signed char, short) LARGER_INT(short, int) LARGER_INT(int, long long) LARGER_INT(long, __int128_t) LARGER_INT(long long, __int128_t) LARGER_INT(unsigned char, unsigned short) LARGER_INT(unsigned short, unsigned int) LARGER_INT(unsigned int, unsigned long long) LARGER_INT(unsigned long, __uint128_t) LARGER_INT(unsigned long long, __uint128_t) #undef LARGER_INT template struct Rational; template struct larger_int> { using type = Rational::type>; }; template using larger_int_t = typename larger_int::type; // https://github.com/miscalculation53/library/tree/wip/math/modint/modint_internal_isprime.hpp namespace internal { template constexpr ll powmod_constexpr(ll x, ll n, T m) { if (m == 1) return 0; using U = make_unsigned_t; using L = larger_int_t; U r = 1, y = safemod(x, m); while (n) { if (n & 1) r = L(r) * y % m; y = L(y) * y % m; n >>= 1; } return r; } template constexpr bool isprime = isprime_constexpr(n); }; namespace internal { template struct policy_static { using mod_type = decltype(M); using value_type = make_unsigned_t; using calc_type = larger_int_t; static constexpr bool is_prime = isprime_constexpr(M); static constexpr value_type init(value_type v) { return v; } static constexpr mod_type val(value_type v); }; }; // https://github.com/miscalculation53/library/tree/wip/math/modint/modint_internal_barrett32.hpp namespace internal { struct barrett32 { uint m; ull im; explicit barrett32(uint m) : m(m), im((ull)(-1) / m + 1) {} uint umod() const { return m; } uint mul(uint a, uint b) const { ull z = a; z *= b; ull x = ull((u128(z) * im) >> 64); ull y = x * m; return uint(z - y + (z < y ? m : 0)); } }; template struct policy_barrett32 { using value_type = uint; using calc_type = ull; using mod_type = int; static constexpr bool is_prime = false; static inline barrett32 reducer{998244353}; static value_type init(value_type v) { return v; } static mod_type val(value_type v); }; }; // https://github.com/miscalculation53/library/tree/wip/math/modint/modint_internal_montgomery64.hpp namespace internal { inline constexpr ull inv64(ull a) { ull x = a; while (a * x != 1) x *= 2 - a * x; return x; } struct montgomery64odd { ull m, im, sq; explicit montgomery64odd(ull m) : m(m), im(inv64(m)), sq(-u128(m) % m) {} ull umod() const { return m; } ull reduce(u128 x) const { auto t = (x + u128(m) * (-im * ull(x))) >> 64; if (t >= m) t -= m; return (ull)t; } ull inv_reduce(i128 v) const { return reduce(u128(v % m + m) * sq); } }; struct montgomery64 { ull m, mx, imx, d, q; uint b; explicit montgomery64(ull m) : m(m) { b = countr_zero(m), mx = m >> b; imx = inv64(mx); d = powmod_constexpr((mx + 1) / 2, b, mx); u128 sq = -u128(mx) % mx; q = (1 + (((sq - 1) * d) << b)) % m; } ull umod() const { return m; } ull reduce(u128 x) const { if (b == 0) { auto t = (x + u128(mx) * (-imx * ull(x))) >> 64; if (t >= m) t -= m; return (ull)t; } ull p = x & MASK(b); x = (x >> b) + p * d; ull y = p << (64 - b); auto t = (x + u128(mx) * (imx * (y - ull(x)))) >> (64 - b); if (t >= m) { t -= m; if (t >= m) t -= m; } return (ull)t; } ull inv_reduce(i128 v) const { return reduce(u128(v % m + m) * q); } }; template struct policy_montgomery64_odd { using value_type = ull; using calc_type = u128; using mod_type = ll; static constexpr bool is_prime = false; static inline montgomery64odd reducer{(1LL << 61) - 1}; static value_type init(value_type v) { return reducer.inv_reduce(v); } static mod_type val(value_type v); }; template struct policy_montgomery64 { using value_type = ull; using calc_type = u128; using mod_type = ll; static constexpr bool is_prime = false; static inline montgomery64 reducer{(1LL << 61) - 1}; static value_type init(value_type v) { return reducer.inv_reduce(v); } static mod_type val(value_type v); }; }; // https://github.com/miscalculation53/library/tree/wip/math/extgcd.hpp namespace internal { template struct modint_impl { using V = typename Policy::value_type; using M = typename Policy::mod_type; using mint = modint_impl; private: V _v; public: modint_impl(); template >> modint_impl(T v); M val() const; friend mint operator+(const mint &lhs, const mint &rhs) { return mint(lhs) += rhs; } friend mint operator-(const mint &lhs, const mint &rhs) { return mint(lhs) -= rhs; } friend mint operator*(const mint &lhs, const mint &rhs) { return mint(lhs) *= rhs; } friend mint operator/(const mint &lhs, const mint &rhs) { return mint(lhs) /= rhs; } friend bool operator==(const mint &lhs, const mint &rhs) { return lhs._v == rhs._v; } friend bool operator!=(const mint &lhs, const mint &rhs) { return lhs._v != rhs._v; } friend M safe_hash_key(const mint &x) { return x.val(); } friend std::istream &operator>>(std::istream &is, mint &x) { long long a; is >> a; x = a; return is; } friend std::ostream &operator<<(std::ostream &os, const mint &x) { os << x.val(); return os; } }; }; template using static_modint32 = internal::modint_impl>; template using dynamic_modint32 = internal::modint_impl>; template using static_modint64 = internal::modint_impl>; template using dynamic_modint64_odd = internal::modint_impl>; template using dynamic_modint64 = internal::modint_impl>; using modint998244353 = static_modint32<998244353>; template struct is_modint : std::false_type { }; template struct is_modint> : std::true_type { }; template inline constexpr bool is_modint_v = is_modint::value; template struct is_static_modint : false_type {}; template struct is_static_modint> : true_type {}; template struct is_static_modint> : true_type {}; template inline constexpr bool is_static_modint_v = is_static_modint::value; template struct is_dynamic_modint : false_type {}; template struct is_dynamic_modint> : true_type {}; template struct is_dynamic_modint> : true_type {}; template struct is_dynamic_modint> : true_type {}; template inline constexpr bool is_dynamic_modint_v = is_dynamic_modint::value; // https://github.com/miscalculation53/library/tree/wip/math/modint/power_table.hpp // https://github.com/miscalculation53/library/tree/wip/math/modint/binomial.hpp template struct Binomial { private: inline static decltype(T::mod()) mod; public: inline static vc fac_, finv_, inv_; }; // https://github.com/miscalculation53/library/tree/wip/math/modint/stom.hpp // https://github.com/miscalculation53/library/tree/wip/math/modint/to_rational.hpp // https://github.com/miscalculation53/library/tree/wip/math/svp2d.hpp namespace cpp_dump { template struct rat_value { T p, q; friend ostream &operator<<(ostream &os, const rat_value &x) { os << x.p; if (x.q != 1) os << '/' << x.q; return os; } }; template inline constexpr bool rat_is_map = false; template inline constexpr bool rat_is_map> = true; template inline constexpr bool rat_is_map> = true; template inline constexpr bool rat_is_map> = true; template inline constexpr bool rat_is_map> = true; struct rat_closure : std::ranges::range_adaptor_closure { }; constexpr rat_closure rat() { return rat_closure{}; } } using mint = modint998244353; // using mint = modint1000000007; // using mint = static_modint<1000000000>; // using mint = modint; void init() { oj(mt.seed(random_device()())); } // https://github.com/miscalculation53/library/tree/wip/algo/subset_sum.hpp // https://github.com/miscalculation53/library/tree/wip/ds/dynamic_bitset.hpp struct DynamicBitset { using Word = ull; static constexpr int word_bits = numeric_limits::digits; private: int n; vc dat; static int word_size(int n) { return (n + word_bits - 1) / word_bits; } static Word low_mask(int k) { return k == word_bits ? ~Word(0) : (Word(1) << k) - 1; } Word last_mask() const { return n % word_bits == 0 ? ~Word(0) : low_mask(n % word_bits); } void trim() { if (!dat.empty()) dat.back() &= last_mask(); } Word get_word(int i) const { int w = i / word_bits, b = i % word_bits; Word x = dat[w] >> b; if (b && w + 1 < SZ(dat)) x |= dat[w + 1] << (word_bits - b); return x; } template DynamicBitset &apply_slice(int l, int r, const DynamicBitset &b, int bl, const F &f) { assert(0 <= l && l <= r && r <= n); assert(0 <= bl && bl + r - l <= b.n); if (l == r) return *this; if constexpr (op == 2) { if (this == &b && bl == 0 && l > 0) { int dw = l / word_bits, db = l % word_bits; int lw = l / word_bits, rw = (r - 1) / word_bits; repi(w, rw, lw - 1, -1) { Word x = dat[w - dw] << db; if (db && w > dw) x |= dat[w - dw - 1] >> (word_bits - db); int lo = max(l, w * word_bits), hi = min(r, (w + 1) * word_bits); Word mask = low_mask(hi - lo) << (lo % word_bits); Word added = x & ~dat[w] & mask; dat[w] |= x & mask; if constexpr (!is_same_v) { while (added) { f(w * word_bits + __builtin_ctzll(added)); added &= added - 1; } } } return *this; } } auto apply_word = [&](int w) { int lo = max(l, w * word_bits), hi = min(r, (w + 1) * word_bits); int len = hi - lo, shift = lo % word_bits; Word mask = low_mask(len) << shift; Word x = (b.get_word(bl + lo - l) & low_mask(len)) << shift; Word old = dat[w], y; if constexpr (op == 0) y = x; else if constexpr (op == 1) y = old & x; else if constexpr (op == 2) y = old | x; else y = old ^ x; dat[w] = (old & ~mask) | (y & mask); if constexpr (!is_same_v) { Word added = dat[w] & ~old & mask; while (added) { f(w * word_bits + __builtin_ctzll(added)); added &= added - 1; } } }; int lw = l / word_bits, rw = (r - 1) / word_bits; if (this == &b && bl < l && l < bl + r - l) repi(w, rw, lw - 1, -1) apply_word(w); else repi(w, lw, rw + 1) apply_word(w); return *this; } public: struct Reference { DynamicBitset *bs; int pos; operator bool() const { return bs->test(pos); } Reference &operator=(bool value) { bs->set(pos, value); return *this; } Reference &operator=(const Reference &ref) { return *this = bool(ref); } Reference &flip() { bs->flip(pos); return *this; } }; DynamicBitset() : n(0) {} DynamicBitset(int n, bool value = false) : n(n), dat(n < 0 ? 0 : word_size(n), value ? ~Word(0) : 0) { assert(n >= 0); trim(); } explicit DynamicBitset(const string &s, char zero = '0', char one = '1') : n(0) { assign(s, zero, one); } int size() const { return n; } bool empty() const { return n == 0; } int capacity() const { return int(dat.capacity()) * word_bits; } void reserve(int n) { assert(n >= 0); dat.reserve(word_size(n)); } void resize(int n, bool value = false) { assert(n >= 0); int old = this->n; dat.resize(word_size(n)); this->n = n; if (value && old < n) set_range(old, n); trim(); } DynamicBitset &assign(const string &s, char zero = '0', char one = '1') { assert(zero != one); n = int(s.size()); dat.assign(word_size(n), 0); repi(i, n) { char c = s[n - 1 - i]; assert(c == zero || c == one); if (c == one) dat[i / word_bits] |= Word(1) << (i % word_bits); } return *this; } bool test(int i) const { assert(0 <= i && i < n); return dat[i / word_bits] >> (i % word_bits) & 1; } bool operator[](int i) const { return test(i); } Reference operator[](int i) { assert(0 <= i && i < n); return {this, i}; } DynamicBitset &set(int i, bool value = true) { assert(0 <= i && i < n); Word mask = Word(1) << (i % word_bits); if (value) dat[i / word_bits] |= mask; else dat[i / word_bits] &= ~mask; return *this; } DynamicBitset &reset(int i) { return set(i, false); } DynamicBitset &flip(int i) { assert(0 <= i && i < n); dat[i / word_bits] ^= Word(1) << (i % word_bits); return *this; } DynamicBitset &set() { fill(ALL(dat), ~Word(0)); trim(); return *this; } DynamicBitset &reset() { fill(ALL(dat), 0); return *this; } DynamicBitset &flip() { fem(x : dat) x = ~x; trim(); return *this; } DynamicBitset &set_range(int l, int r, bool value = true) { assert(0 <= l && l <= r && r <= n); if (!value) return reset_range(l, r); if (l == r) return *this; int lw = l / word_bits, rw = (r - 1) / word_bits; if (lw == rw) dat[lw] |= low_mask((r - 1) % word_bits + 1) & ~low_mask(l % word_bits); else { dat[lw] |= ~low_mask(l % word_bits); fill(dat.begin() + lw + 1, dat.begin() + rw, ~Word(0)); dat[rw] |= low_mask((r - 1) % word_bits + 1); } trim(); return *this; } DynamicBitset &reset_range(int l, int r) { assert(0 <= l && l <= r && r <= n); if (l == r) return *this; int lw = l / word_bits, rw = (r - 1) / word_bits; if (lw == rw) dat[lw] &= ~(low_mask((r - 1) % word_bits + 1) & ~low_mask(l % word_bits)); else { dat[lw] &= low_mask(l % word_bits); fill(dat.begin() + lw + 1, dat.begin() + rw, 0); dat[rw] &= ~low_mask((r - 1) % word_bits + 1); } return *this; } DynamicBitset &flip_range(int l, int r) { assert(0 <= l && l <= r && r <= n); if (l == r) return *this; int lw = l / word_bits, rw = (r - 1) / word_bits; if (lw == rw) dat[lw] ^= low_mask((r - 1) % word_bits + 1) & ~low_mask(l % word_bits); else { dat[lw] ^= ~low_mask(l % word_bits); repi(w, lw + 1, rw) dat[w] = ~dat[w]; dat[rw] ^= low_mask((r - 1) % word_bits + 1); } trim(); return *this; } int count() const { int res = 0; fec(x : dat) res += __builtin_popcountll(x); return res; } int count(int l, int r) const { assert(0 <= l && l <= r && r <= n); if (l == r) return 0; int lw = l / word_bits, rw = (r - 1) / word_bits; if (lw == rw) return __builtin_popcountll(dat[lw] & low_mask((r - 1) % word_bits + 1) & ~low_mask(l % word_bits)); int res = __builtin_popcountll(dat[lw] & ~low_mask(l % word_bits)); repi(w, lw + 1, rw) res += __builtin_popcountll(dat[w]); return res + __builtin_popcountll(dat[rw] & low_mask((r - 1) % word_bits + 1)); } bool any() const { fec(x : dat) if (x) return true; return false; } bool any(int l, int r) const { return count(l, r) != 0; } bool none() const { return !any(); } bool none(int l, int r) const { return !any(l, r); } bool all() const { return count() == n; } bool all(int l, int r) const { return count(l, r) == r - l; } int find_first(bool value = true) const { return find_next(-1, value); } int find_next(int i, bool value = true) const { assert(-1 <= i && i < n); i++; if (i == n) return n; int w = i / word_bits, b = i % word_bits; Word x = (value ? dat[w] : ~dat[w]) & (~Word(0) << b); while (true) { if (x) { int res = w * word_bits + __builtin_ctzll(x); return min(res, n); } if (++w == SZ(dat)) return n; x = value ? dat[w] : ~dat[w]; } } int find_last(bool value = true) const { return find_prev(n, value); } int find_prev(int i, bool value = true) const { assert(0 <= i && i <= n); if (i == 0) return -1; i--; int w = i / word_bits, b = i % word_bits; Word x = (value ? dat[w] : ~dat[w]) & low_mask(b + 1); while (true) { if (x) return w * word_bits + 63 - __builtin_clzll(x); if (w-- == 0) return -1; x = value ? dat[w] : ~dat[w]; } } DynamicBitset &operator&=(const DynamicBitset &b) { assert(n == b.n); repi(i, SZ(dat)) dat[i] &= b.dat[i]; return *this; } DynamicBitset &operator|=(const DynamicBitset &b) { assert(n == b.n); repi(i, SZ(dat)) dat[i] |= b.dat[i]; return *this; } DynamicBitset &operator^=(const DynamicBitset &b) { assert(n == b.n); repi(i, SZ(dat)) dat[i] ^= b.dat[i]; return *this; } friend DynamicBitset operator&(DynamicBitset a, const DynamicBitset &b) { return a &= b; } friend DynamicBitset operator|(DynamicBitset a, const DynamicBitset &b) { return a |= b; } friend DynamicBitset operator^(DynamicBitset a, const DynamicBitset &b) { return a ^= b; } DynamicBitset operator~() const { return DynamicBitset(*this).flip(); } DynamicBitset &operator<<=(int k) { assert(k >= 0); if (k >= n) return reset(); if (k == 0) return *this; int dw = k / word_bits, db = k % word_bits; repi(i, SZ(dat) - 1, dw - 1, -1) { Word x = dat[i - dw] << db; if (db && i > dw) x |= dat[i - dw - 1] >> (word_bits - db); dat[i] = x; } fill(dat.begin(), dat.begin() + dw, 0); trim(); return *this; } DynamicBitset &operator>>=(int k) { assert(k >= 0); if (k >= n) return reset(); if (k == 0) return *this; int dw = k / word_bits, db = k % word_bits, m = SZ(dat); repi(i, m - dw) { Word x = dat[i + dw] >> db; if (db && i + dw + 1 < m) x |= dat[i + dw + 1] << (word_bits - db); dat[i] = x; } fill(dat.end() - dw, dat.end(), 0); trim(); return *this; } DynamicBitset operator<<(int k) const { return DynamicBitset(*this) <<= k; } DynamicBitset operator>>(int k) const { return DynamicBitset(*this) >>= k; } DynamicBitset &assign_slice(int l, int r, const DynamicBitset &b, int bl) { return apply_slice<0>(l, r, b, bl, nullptr); } DynamicBitset &and_slice(int l, int r, const DynamicBitset &b, int bl) { return apply_slice<1>(l, r, b, bl, nullptr); } DynamicBitset &or_slice(int l, int r, const DynamicBitset &b, int bl) { return apply_slice<2>(l, r, b, bl, nullptr); } template DynamicBitset &or_slice(int l, int r, const DynamicBitset &b, int bl, const F &f) { return apply_slice<2>(l, r, b, bl, f); } [[gnu::always_inline]] DynamicBitset &xor_slice(int l, int r, const DynamicBitset &b, int bl) { if (l == bl && l % word_bits == 0 && r == n && n == b.n) { assert(0 <= l && l <= r); repi(w, l / word_bits, SZ(dat)) dat[w] ^= b.dat[w]; return *this; } return apply_slice<3>(l, r, b, bl, nullptr); } void push_back(bool value) { int i = n; resize(n + 1); if (value) set(i); } void pop_back() { assert(n > 0); resize(n - 1); } string to_string(char zero = '0', char one = '1') const { assert(zero != one); string res(n, zero); repi(i, n) if (test(i)) res[n - 1 - i] = one; return res; } friend bool operator==(const DynamicBitset &a, const DynamicBitset &b) { return a.n == b.n && a.dat == b.dat; } friend bool operator!=(const DynamicBitset &a, const DynamicBitset &b) { return !(a == b); } friend bool operator<(const DynamicBitset &a, const DynamicBitset &b) { assert(a.n == b.n); repi(i, SZ(a.dat) - 1, -1, -1) if (a.dat[i] != b.dat[i]) return a.dat[i] < b.dat[i]; return false; } friend bool operator>(const DynamicBitset &a, const DynamicBitset &b) { return b < a; } friend bool operator<=(const DynamicBitset &a, const DynamicBitset &b) { return !(b < a); } friend bool operator>=(const DynamicBitset &a, const DynamicBitset &b) { return !(a < b); } }; istream &operator>>(istream &is, DynamicBitset &a) { string s; is >> s; if (is) a.assign(s); return is; } ostream &operator<<(ostream &os, const DynamicBitset &a) { return os << a.to_string(); } struct SubsetSum; struct SubsetSumFromFrequency { private: friend struct SubsetSum; int s; vc> val_cnt; DynamicBitset dp; vc time; vc history; bool keep_history; void build(const vc> &freq, int smax) { s = smax; assert(s >= 0); val_cnt.clear(); history.clear(); ll sm = 0; for (auto [v, c] : freq) { assert(v > 0 && c >= 0); if (v > s) continue; chmin(c, s / v); sm = min(s, sm + ll(v) * c); } s = int(sm); dp.resize(s + 1); dp.reset(); dp.set(0); for (auto [v, c] : freq) { if (v > s) continue; chmin(c, s / v); for (ll k = 1; c > 0; k *= 2) { int x = int(min(c, k)); c -= x; val_cnt.eb(v, x); } } ll bitset_bytes = ll((s + DynamicBitset::word_bits) / DynamicBitset::word_bits) * ll(sizeof(DynamicBitset::Word)); keep_history = ll(val_cnt.size()) * bitset_bytes < ll(s + 1) * ll(sizeof(int)); if (keep_history) history.reserve(val_cnt.size()); else { time.assign(s + 1, -1); time[0] = 0; } int hi = 0; repi(t, SZ(val_cnt)) { auto [v, c] = val_cnt[t]; int w = v * c; int r = min(s, hi + w) + 1; if (keep_history) { dp.or_slice(w, r, dp, 0); history.eb(dp); } else dp.or_slice(w, r, dp, 0, [&](int i) { time[i] = t + 1; }); hi = r - 1; if (hi == s && (t & 63) == 63 && dp.all()) { val_cnt.resize(t + 1); if (keep_history) history.resize(t + 1); break; } } } public: SubsetSumFromFrequency() : s(0), dp(1), time(1, 0), keep_history(false) { dp.set(0); } bool exists(int x) const { return 0 <= x && x <= s && dp.test(x); } const DynamicBitset &reachable() const { return dp; } pair>> answer(int x) const { if (!exists(x)) return {false, {}}; vc> res; int y = x; repi(t, SZ(val_cnt) - 1, -1, -1) { auto [v, c] = val_cnt[t]; int w = v * c; bool can = false; if (y >= w) { if (keep_history) can = t == 0 ? y == w : history[t - 1].test(y - w); else can = time[y - w] != -1 && time[y - w] <= t; } if (can) { y -= w; if (res.empty() || res.back().first != v) res.eb(v, 0); res.back().second += c; } } return {true, res}; } }; struct SubsetSum { private: int n, s, xmax; ll negsum; vc isneg; vc> elems; SubsetSumFromFrequency ss; public: SubsetSum() : n(0), s(-1), xmax(-1), negsum(0) {} template SubsetSum(const vc &a, int smax) : n(SZ(a)), xmax(smax), negsum(0) { static_assert(is_integral_ext); isneg.assign(n, false); repi(i, n) if (a[i] < 0) { isneg[i] = true; negsum += ll(a[i]); } ll shifted_s = ll(smax) - negsum; if (shifted_s < 0) { s = -1; return; } ll sm = 0; fec(a_i : a) { ll x = ll(a_i); if (x < 0) x = -x; if (x <= shifted_s) sm = min(shifted_s, sm + x); } s = int(sm); repi(i, n) { ll x = ll(a[i]); if (x < 0) { if (x < -ll(s)) continue; x = -x; } if (x <= s) { int v = int(x); if (v) elems.eb(v, i); } } sort(elems.begin(), elems.end()); vc> freq; for (auto [v, i] : elems) { if (freq.empty() || freq.back().first != v) freq.eb(v, 0); ++freq.back().second; } ss.build(freq, s); s = ss.reachable().size() - 1; } bool exists(int x) const { ll y = ll(x) - negsum; return x <= xmax && 0 <= y && y <= s && ss.exists(int(y)); } const DynamicBitset &reachable() const { static const DynamicBitset empty; return s < 0 ? empty : ss.reachable(); } ll min_sum() const { return negsum; } pair> answer(int x) const { ll y = ll(x) - negsum; if (x > xmax || !(0 <= y && y <= s)) return {false, {}}; auto [ok, cnt] = ss.answer(int(y)); if (!ok) return {false, {}}; vc res(n, false); int p = elems.size(); for (auto [v, c] : cnt) { while (p && elems[p - 1].first > v) p--; int q = p; while (q && elems[q - 1].first == v) q--; assert(p - q >= c); repi(k, c) res[elems[q + k].second] = true; p = q; } repi(i, n) if (isneg[i]) res[i] = !res[i]; return {true, res}; } }; void main2() { LL(N, M); VEC(ll, N, U); VEC(ll, M, T); SubsetSum ss(T, SUM(T) + 1); auto res = ss.reachable(); local(rep(i, SZ(res)) if (res.test(i)) dump(i);); DynamicBitset res2(SUM(T) + MAX(U) + 1); fe(u : U) res2.or_slice(u, min(SZ(res2), u + SZ(res)), res, 0); PRINT(res2.count()); local(rep(i, SZ(res2)) if (res2.test(i)) dump(i);); } void test() { } // https://github.com/miscalculation53/library/tree/wip/template/template_main.hpp template struct Main { Main() { cauto CERR = [](string val, string color) { string s = "\033[" + color + "m" + val + "\033[m"; }; cout << fixed << setprecision(20); init(); CERR("\n[SINGLE_TESTCASE]\n\n", "36"); main2(); } }; Main main_dummy; int main() {}