結果
問題 | No.137 貯金箱の焦り |
ユーザー | Dal Tao |
提出日時 | 2024-08-11 16:13:03 |
言語 | C++23 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 811 ms / 5,000 ms |
コード長 | 27,310 bytes |
コンパイル時間 | 1,711 ms |
コンパイル使用メモリ | 158,444 KB |
実行使用メモリ | 5,376 KB |
最終ジャッジ日時 | 2024-08-11 16:13:09 |
合計ジャッジ時間 | 6,226 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge5 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
5,248 KB |
testcase_01 | AC | 2 ms
5,376 KB |
testcase_02 | AC | 2 ms
5,376 KB |
testcase_03 | AC | 2 ms
5,376 KB |
testcase_04 | AC | 8 ms
5,376 KB |
testcase_05 | AC | 2 ms
5,376 KB |
testcase_06 | AC | 5 ms
5,376 KB |
testcase_07 | AC | 3 ms
5,376 KB |
testcase_08 | AC | 3 ms
5,376 KB |
testcase_09 | AC | 6 ms
5,376 KB |
testcase_10 | AC | 3 ms
5,376 KB |
testcase_11 | AC | 1 ms
5,376 KB |
testcase_12 | AC | 811 ms
5,376 KB |
testcase_13 | AC | 53 ms
5,376 KB |
testcase_14 | AC | 373 ms
5,376 KB |
testcase_15 | AC | 329 ms
5,376 KB |
testcase_16 | AC | 312 ms
5,376 KB |
testcase_17 | AC | 107 ms
5,376 KB |
testcase_18 | AC | 293 ms
5,376 KB |
testcase_19 | AC | 355 ms
5,376 KB |
testcase_20 | AC | 3 ms
5,376 KB |
testcase_21 | AC | 164 ms
5,376 KB |
testcase_22 | AC | 21 ms
5,376 KB |
testcase_23 | AC | 20 ms
5,376 KB |
testcase_24 | AC | 79 ms
5,376 KB |
testcase_25 | AC | 240 ms
5,376 KB |
ソースコード
//Timestamp: 2024-08-11 15:12:19 #define DROP #ifdef ONLINE #undef LOCAL #endif #ifndef LOCAL #undef _GLIBCXX_DEBUG #undef _DEBUG #endif #include <cassert> #include <cmath> #include <cstring> #include <deque> #include <fstream> //#include <ext/pb_ds/assoc_container.hpp> #include <functional> #include <iomanip> #include <iostream> #include <map> #include <queue> #include <tuple> #include <type_traits> #include <chrono> #include <random> #include <complex> #include <bitset> #include <set> #include <list> #include <array> //#include "compiler_hint.cpp" template <class T, int S> struct MDVecDef { using Type = std::vector<typename MDVecDef<T, S - 1>::Type>; template <typename... Args> static Type Make(int n, Args... args) { return Type(n, MDVecDef<T, S - 1>::Make(args...)); } }; template <class T> struct MDVecDef<T, 0> { using Type = T; static Type Make(T val = T()) { return val; } }; template <class T, int S = 1> using MDVec = typename MDVecDef<T, S>::Type; #ifndef M_PI #define M_PI 3.14159265358979323851280895940618620443274267017841L #endif #ifndef M_E #define M_E 2.718281828459045235428168107993940338928950950503355L #endif #ifdef LOCAL #define Assert(x) assert(x) #define DebugRun(X) X #define DebugPoint int _x_ = 0; _x_++; #else #define Debug(...) 42 #define DebugFmtln(...) 42 #define Assert(x) 42 #define DebugRun(X) #define DebugPoint #endif #define Trace(x) DebugFmtln("Line %d: %s", __LINE__, #x) template<class T> inline T DebugRet(T x) { Debug(x); return x; } #define const_ref(T) const T & #define mut_ref(T) T & #define let auto #define var auto #define MEMSET0(X) std::memset(&X, 0, sizeof(X)) #define Size(T) int((T).size()) #define All(data) data.begin(), data.end() #define MakeUnique(data) data.resize(std::unique(All(data)) - data.begin()) #define MakeUniqueAndSort(data) Sort(All(data)); MakeUnique(data) #define MakeAttribute(struct_name, Type, attr_name) \ struct struct_name { \ using attr_name ## _type = Type; \ Type attr_name; \ mut_ref(Type) get_##attr_name() { return attr_name; } \ const_ref(Type) get_##attr_name() const { return attr_name; } \ }; #define MakeTemplateAttribute(struct_name, attr_name) \ template <class T> \ struct struct_name { \ using attr_name##_type = T; \ T attr_name; \ mut_ref(T) get_##attr_name() { return attr_name; } \ const_ref(T) get_##attr_name() const { return attr_name; } \ }; #define ImplDefaultEq(name) \ bool operator==(const name &a, const name &b) { \ return std::memcmp(&a, &b, sizeof(name)) == 0; \ } \ bool operator!=(const name &a, const name &b) { return !(a == b); } #define ImplDefaultComparision(name) \ bool operator>(const name &rhs) const { return rhs < *this; } \ bool operator<=(const name &rhs) const { return !(*this > rhs); } \ bool operator>=(const name &rhs) const { return !(*this < rhs); } #define ImplArithmeticAssignOperation(name) \ name &operator+=(const name &rhs) { return *this = (*this) + rhs; } \ name &operator-=(const name &rhs) { return *this = (*this) - rhs; } \ name &operator*=(const name &rhs) { return *this = (*this) * rhs; } \ name &operator/=(const name &rhs) { return *this = (*this) / rhs; } #define IsType(Type, param, ret_type) \ template <typename OnlyWhenArg = param> \ enable_if_t<is_same_v<OnlyWhenArg, param> && is_same_v<OnlyWhenArg, Type>, \ ret_type> #define IsBool(param, ret_type) \ template <bool OnlyWhenArg = param> \ enable_if_t<OnlyWhenArg == (param) && OnlyWhenArg, ret_type> #define IsBoolStatic(param, ret_type) \ template <bool OnlyWhenArg = param> \ static enable_if_t<OnlyWhenArg == (param) && OnlyWhenArg, ret_type> #define MakeAnnotation(name) \ template <class T> \ struct is_##name { \ static const bool value = false; \ }; \ template <class T> \ inline constexpr bool is_##name##_v = is_##name<T>::value; #define AssignAnnotation(cls, annotation) \ template <> \ struct is_##annotation<cls> { \ static const bool value = true; \ }; #define AssignAnnotationTemplate(cls, annotation, type) \ template <type T> \ struct is_##annotation<cls<T>> { \ static const bool value = true; \ }; #define FunctionAlias(from, to) \ template <typename... Args> \ inline auto to(Args &&...args) \ ->decltype(from(std::forward<Args>(args)...)) { \ return from(std::forward<Args>(args)...); \ } #define CastToScalar(field, type) \ operator type() const { return type(field); } #define CastToAllScalar(field) \ CastToScalar(field, i8); \ CastToScalar(field, u8); \ CastToScalar(field, i16); \ CastToScalar(field, u16); \ CastToScalar(field, i32); \ CastToScalar(field, u32); \ CastToScalar(field, i64); \ CastToScalar(field, u64); \ CastToScalar(field, f32); \ CastToScalar(field, f64); \ CastToScalar(field, f80); #define COMMA , #ifndef LOCAL std::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count()); #else std::mt19937 rng(0); #endif template <class T> T random_choice(T l, T r, std::mt19937 &gen = rng) { std::uniform_int_distribution<T> random(l, r); return random(gen); } namespace dalt { #ifndef LOCAL struct Timer {explicit Timer(const char* m) {}void stop() const {}}; #else #endif } using i8 = char; using i16 = short; using i32 = int; using i64 = long long; using u8 = unsigned char; using u16 = unsigned short; using u32 = unsigned int; using u64 = unsigned long long; using usize = size_t; using f32 = float; using f64 = double; // 16 exp, 64 precision using f80 = long double; FunctionAlias(std::lower_bound, LowerBound); FunctionAlias(std::upper_bound, UpperBound); FunctionAlias(std::unique, Unique); FunctionAlias(std::swap, Swap); FunctionAlias(std::min, Min); FunctionAlias(std::max, Max); FunctionAlias(std::abs, Abs); FunctionAlias(std::sin, Sin); FunctionAlias(std::asin, Asin); FunctionAlias(std::cos, Cos); FunctionAlias(std::acos, Acos); FunctionAlias(std::tan, Tan); FunctionAlias(std::atan, Atan); FunctionAlias(std::sort, Sort); FunctionAlias(std::fill, Fill); FunctionAlias(std::move, Move); FunctionAlias(std::reverse, Reverse); FunctionAlias(std::max_element, MaxElement); FunctionAlias(std::min_element, MinElement); FunctionAlias(std::make_tuple, MakeTuple); FunctionAlias(std::make_pair, MakePair); FunctionAlias(std::clamp, Clamp); FunctionAlias(std::shuffle, Shuffle); FunctionAlias(std::to_string, ToString); FunctionAlias(std::tie, Tie); FunctionAlias(std::get<0>, Get0); FunctionAlias(std::get<1>, Get1); FunctionAlias(std::get<2>, Get2); FunctionAlias(std::get<3>, Get3); FunctionAlias(std::get<4>, Get4); template <typename _Signature> using Function = std::function<_Signature>; template <typename _Signature> using Func = Function<_Signature>; using Str = std::string; using String = Str; using StringStream = std::stringstream; using IStream = std::istream; using OStream = std::ostream; using std::enable_if; using std::enable_if_t; using std::is_base_of; using std::is_base_of_v; using std::is_floating_point; using std::is_floating_point_v; using std::is_integral; using std::is_integral_v; using std::is_arithmetic; using std::is_arithmetic_v; using std::is_same; using std::is_same_v; using std::tie; auto &Stderr = std::cerr; auto &Stdin = std::cin; auto &Stdout = std::cout; template <class T> using Less = std::less<T>; template <class T> using Greater = std::greater<T>; template <typename _Key, typename _Tp, typename _Compare = Less<_Key>> using TreeMap = std::map<_Key, _Tp, _Compare>; template <typename _Key, typename _Compare = Less<_Key>> using TreeSet = std::set<_Key, _Compare>; template <typename _Key, typename _Compare = std::less<_Key>, typename _Alloc = std::allocator<_Key>> using MultiTreeSet = std::multiset<_Key, _Compare, _Alloc>; template <class T> using Deque = std::deque<T>; template <class T> using Queue = std::queue<T>; template <class T> using Vec = std::vector<T>; template <class T> using Reducer = Func<T(const T &, const T &)>; template <class T> using Comparator = Func<bool(const T &, const T &)>; template <class T> using Indexer = Func<T(i32)>; template <class T> using Indexer2 = Func<T(i32, i32)>; template <class A, class B = A, class C = A> using Adder = Func<C(const A &, const B &)>; template <class I> using Checker = Func<bool(const I &)>; template <class A, class B> using BiChecker = Func<bool(const A &, const B &)>; template <class T> using Consumer = Func<void(const T &)>; template<class T> using Supplier = Func<T()>; template <class FIRST, class SECOND> using BiConsumer = Func<void(const FIRST &, const SECOND &)>; template <class F, class T = F> using Mapper = Func<T(const F &)>; template <class T> using MinHeap = std::priority_queue<T, Vec<T>, Greater<T>>; template <class T> using MaxHeap = std::priority_queue<T, Vec<T>, Less<T>>; template <class T, usize S> using Array = std::array<T, S>; template <typename... _Elements> using Tuple = std::tuple<_Elements...>; template <class T, class = enable_if_t<is_floating_point_v<T>>> using Complex = std::complex<T>; template <class A, class B> using Pair = std::pair<A, B>; namespace dalt { template <class T> IStream& operator>>(IStream& is, Vec<T>& val) { for (auto& v : val) { is >> v; } return is; } #define VEC_OP(op) \ template <class T> \ Vec<T>& operator op(Vec<T>& data, T x) { \ for (auto& v : data) { \ v op x; \ } \ return data; \ } VEC_OP(+=) VEC_OP(-=) VEC_OP(*=) VEC_OP(/=) VEC_OP(%=) VEC_OP(^=) VEC_OP(&=) VEC_OP(|=) VEC_OP(==) VEC_OP(!=) template <class T> int Compare(const Vec<T>& lhs, const Vec<T>& rhs) { for(int i = 0; i < Size(lhs) && i < Size(rhs); i++) { if(lhs[i] != rhs[i]) { return lhs[i] < rhs[i] ? -1 : 1; } } return Size(lhs) < Size(rhs) ? -1 : Size(lhs) > Size(rhs) ? 1 : 0; } template <class T> bool operator<(const Vec<T>& lhs, const Vec<T>& rhs) { return Compare(lhs, rhs) < 0; } template <class T> bool operator>(const Vec<T>& lhs, const Vec<T>& rhs) { return Compare(lhs, rhs) > 0; } template <class T> bool operator<=(const Vec<T>& lhs, const Vec<T>& rhs) { return Compare(lhs, rhs) <= 0; } template <class T> bool operator>=(const Vec<T>& lhs, const Vec<T>& rhs) { return Compare(lhs, rhs) >= 0; } } // namespace dalt //#include "array_adder.cpp" using namespace dalt; namespace dalt { template <class T> struct Optional { using Self = Optional<T>; private: T val; bool show_up; public: Optional(const T &arg_val) : val(arg_val), show_up(true) {} Optional(const T &&arg_val) : val(arg_val), show_up(true) {} Optional() : show_up(false) {} const T &value() const { Assert(show_up); return val; } T &value() { Assert(show_up); return val; } T &operator*() { return value(); } const T &operator*() const { return value(); } bool is_some() const { return show_up; } bool is_none() const { return !show_up; } const T *operator->() const { return &value(); } T *operator->() { return &value(); } inline operator T() const { return value(); } T or_else(T def) const { if (is_some()) { return val; } else { return def; } } template <class E> Optional<E> map(const Mapper<T, E> &mapper) const { if (is_some()) { return mapper(value()); } else { return Optional<E>(); } } bool operator==(const Self &b) const { return show_up == b.show_up && (!show_up || val == b.val); } }; template <class E> bool operator!=(const Optional<E> &a, const Optional<E> &b) { return !(a == b); } template <class E> OStream &operator<<(OStream &os, const Optional<E> &v) { if (v.is_none()) { os << "{}"; } else { os << '{' << v.value() << '}'; } return os; } } // namespace dalt namespace dalt { template <class T> inline enable_if_t<is_integral_v<T>, T> Gcd(T a, T b) { while (b != 0) { a %= b; Swap(a, b); } return a; } // ret_value = [x, y, gcd(a,b)] that x * a + y * b = gcd(a, b) template <class T> inline enable_if_t<is_integral_v<T>, Array<T, 3>> ExtGcd(T a, T b) { if (b == 0) { return Array<T, 3>{1, 0, a}; } auto div = a / b; auto ans = ExtGcd(b, a - b * div); auto x = ans[0]; auto y = ans[1]; return Array<T, 3>{y, x - a / b * y, ans[2]}; } template <class T> inline enable_if_t<is_integral_v<T>, Optional<T>> PossibleModInverse( T a, T modulus) { auto res = ExtGcd(a, modulus); if (res[2] == 1) { auto ans = res[0] % modulus; if (ans < 0) { ans += modulus; } return ans; } return {}; } } // namespace dalt namespace dalt { template <class T, class E> T Modular(E val, T mod) { val = val % mod; if (val < 0) { val = val + mod; } return T(val); } template<class T> inline T MulMod(T a, T b, T modulus) { i64 res = i64(a) * i64(b) % modulus; return T(res); } template<> inline i64 MulMod<i64>(i64 a, i64 b, i64 modulus) { #ifdef __SIZEOF_INT128__ // do some fancy stuff here return __int128_t(a) * __int128_t(b) % modulus; #else // do some fallback stuff here i64 k = roundl((f80)a / modulus * b); i64 res = (a * b - k * modulus) % modulus; if (res < 0) { res += modulus; } return res; #endif } template <class T> inline enable_if_t<is_integral_v<T>, T> AddMod(T a, T b, T modulus) { T res = a + b; if (res >= modulus) { res -= modulus; } return res; } template <class T, class E> inline enable_if_t<is_integral_v<T> && is_integral_v<E>, T> PowMod(T x, E exp, T modulus) { Assert(exp >= E(0)); if (exp == E(0)) { return modulus == T(1) ? T(0) : T(1); } T ans = PowMod(x, exp >> 1, modulus); ans = MulMod(ans, ans, modulus); if (exp & T(1)) { ans = MulMod(ans, x, modulus); } return ans; } template <class T> inline enable_if_t<is_integral_v<T>, T> SubMod(T a, T b, T modulus) { T res = a - b; if (res < T(0)) { res += modulus; } return res; } } // namespace dalt namespace dalt { template <class A, class B> inline A& Chmin(A& a, const B& b) { if (a > b) { a = b; } return a; } template <class T> inline T& Chmin(T& a, const T& b, const Comparator<T> &comp) { if (comp(b, a)) { a = b; } return a; } template <class A, class B> inline A& Chmax(A& a, const B& b) { if (a < b) { a = b; } return a; } template <class T> inline T& Chmax(T& a, const T& b, const Comparator<T>& comp) { if (comp(a, b)) { a = b; } return a; } template <class T> inline T& AddTo(T& a, const T& b) { a = a + b; return a; } template <class T> inline T& MulTo(T& a, const T& b) { a = a * b; return a; } template <class T> inline T& SubFrom(T& a, const T& b) { a = a - b; return a; } template <class T> inline T& DivFrom(T& a, const T& b) { a = a / b; return a; } template <class T, class E> constexpr enable_if_t<is_integral_v<E>, T> PowBinaryLift(T x, E n) { if (n == E(0)) { return T(1); } auto ans = PowBinaryLift(x, n >> 1); ans = ans * ans; if (n & 1) { ans = ans * x; } return ans; } template <class T> inline T MulLimit(T a, T b, T max, T def) { if (a == T(0) || b == T(0)) { return T(0); } // a * b <= max // a <= max / b // a <= floor(max / b) if (a <= max / b) { return a * b; } else { return def; } } template <class T> inline T MulLimit(T a, T b, T max) { return MulLimit(a, b, max, max); } template <class T> inline T AddLimit(T a, T b, T max, T def) { if (a <= max - b) { return a + b; } else { return def; } } template <class T> inline T AddLimit(T a, T b, T max) { return AddLimit(a, b, max, max); } i64 Round(f32 x) { return roundf(x); } i64 Round(f64 x) { return round(x); } i64 Round(f80 x) { return roundl(x); } //l + ... + r template<class T> T SumOfInterval(T l, T r) { if(l > r) { return T(0); } return (l + r) * (r - l + 1) / T(2); } template<class T> T Pow2(T x) { return x * x; } } // namespace dalt namespace dalt { // using Type = T; // static T modulus; // static T primitive_root; MakeAnnotation(modular); template <class T, i64 M, i64 PR = -1, i64 PHI = M - 1> struct StaticModular { static_assert(T(M + M) >= 0); static_assert(is_integral_v<T>); const static T modulus = M; const static T primitive_root = PR; const static T phi = PHI; using Type = T; }; template <class T, i64 M, i64 PR, i64 PHI> struct is_modular<StaticModular<T, M, PR, PHI>> { static const bool value = true; }; using MOD998244353 = StaticModular<i32, 998244353, 3>; using MOD1004535809 = StaticModular<i32, 1004535809, 3>; using MOD1000000007 = StaticModular<i32, 1000000007, 5>; using MOD1000000009 = StaticModular<i32, 1000000009, 13>; using MOD_BIG = StaticModular<i64, 2305843009213693951, -1>; // last used: -2 template <class T = i32, i64 CID = 0, i64 ID = 0> struct DynamicModular { static_assert(is_integral_v<T>); static T modulus; static T primitive_root; static T phi; static void Register(T _modulus, T _primitive_root = T(), T _phi = T()) { modulus = _modulus; primitive_root = _primitive_root; phi = _phi; } using Type = T; }; template <class T, i64 CID, i64 ID> T DynamicModular<T, CID, ID>::modulus = T(); template <class T, i64 CID, i64 ID> T DynamicModular<T, CID, ID>::primitive_root = T(); template <class T, i64 CID, i64 ID> T DynamicModular<T, CID, ID>::phi = T(); template <class T, i64 CID, i64 ID> struct is_modular<DynamicModular<T, CID, ID>> { static const bool value = true; }; MakeAnnotation(modint); MakeAnnotation(modint_32); #define MOD MODULAR::modulus #define SELF ModInt<MODULAR> #define TEMPLATE_ARGS template <class MODULAR> TEMPLATE_ARGS struct ModInt { using Modular = MODULAR; using Type = typename MODULAR::Type; static_assert(is_modular_v<MODULAR>); static_assert(is_integral_v<Type>); Type value; using Self = SELF; ModInt() : value(0) {} ModInt(const Type &v) { value = v; if (value < 0 || value >= MOD) { value %= MOD; if (value < 0) { value += MOD; } } Assert(value >= 0); } static Self nil() { Self res; res.value = -1; return res; } bool is_nil() { return value == -1; } explicit operator Type() const { return value; } static Type modulus() { return MOD; } static Type primitive_root() { return Modular::primitive_root; } Self operator-() const { return Self(0) - *this; } template <class F> static enable_if_t<is_integral_v<F>, Self> of(F v) { v %= MOD; if (v < 0) { v += MOD; } return Self(v); } Optional<Self> possible_inv() const { auto raw_optional_inv = PossibleModInverse(value, MOD); if (raw_optional_inv.is_some()) { return Self(raw_optional_inv.value()); } else { return {}; } } Self operator+(const Self &rhs) const { auto res = value + rhs.value; if (res >= MOD) { res -= MOD; } return res; } Self operator-(const Self &rhs) const { auto res = value - rhs.value; if (res < Type(0)) { res += MOD; } return res; } Self operator/(const SELF &rhs) const { auto inv = Self(rhs.possible_inv().value()); return (*this) * inv; } bool operator==(const Self &b) const { return value == b.value; } bool operator!=(const Self &b) const { return value != b.value; } bool operator<(const Self &b) const { return value < b.value; } ImplDefaultComparision(Self); ImplArithmeticAssignOperation(Self); template <class E> enable_if_t<is_integral_v<E>, Self> pow(E n) { return PowBinaryLift(*this, n); } friend inline IStream &operator>>(IStream &is, Self &x) { Type val; is >> val; x = Self::of(val); return is; } friend inline OStream &operator<<(OStream &os, const Self &x) { os << x.value; return os; } }; TEMPLATE_ARGS inline enable_if_t<!is_same_v<MODULAR, MOD_BIG>, SELF> operator*( const SELF &a, const SELF &b) { return SELF(MulMod(a.value, b.value, MOD)); } TEMPLATE_ARGS inline enable_if_t<is_same_v<MODULAR, MOD_BIG>, SELF> operator*( const SELF &x, const SELF &y) { static u64 mask = (u64(1) << 32) - 1; static u64 mod = MOD_BIG::modulus; u64 a = x.value; u64 b = y.value; u64 l1 = a & mask; u64 h1 = (a >> 32) & mask; u64 l2 = b & mask; u64 h2 = (b >> 32) & mask; u64 l = l1 * l2; u64 m = l1 * h2 + l2 * h1; u64 h = h1 * h2; u64 ret = (l & mod) + (l >> 61) + (h << 3) + (m >> 29) + ((m << 35) >> 3) + 1; ret = (ret & mod) + (ret >> 61); ret = (ret & mod) + (ret >> 61); return SELF(ret - 1); } TEMPLATE_ARGS struct is_modint<ModInt<MODULAR>> { static const bool value = true; }; TEMPLATE_ARGS struct is_modint_32<ModInt<MODULAR>> { static const bool value = is_same_v<typename MODULAR::Type, i32>; }; #undef TEMPLATE_TYPE #undef MOD using ModInt998244353 = ModInt<MOD998244353>; using ModInt1000000007 = ModInt<MOD1000000007>; using ModInt1000000009 = ModInt<MOD1000000009>; using ModInt1004535809 = ModInt<MOD1004535809>; } // namespace dalt using namespace std; template <uint32_t mod> struct LazyMontgomeryModInt { using mint = LazyMontgomeryModInt; using i32 = int32_t; using u32 = uint32_t; using u64 = uint64_t; static constexpr u32 get_r() { u32 ret = mod; for (i32 i = 0; i < 4; ++i) ret *= 2 - mod * ret; return ret; } static constexpr u32 r = get_r(); static constexpr u32 n2 = -u64(mod) % mod; static_assert(mod < (1 << 30), "invalid, mod >= 2 ^ 30"); static_assert((mod & 1) == 1, "invalid, mod % 2 == 0"); static_assert(r * mod == 1, "this code has bugs."); u32 a; constexpr LazyMontgomeryModInt() : a(0) {} constexpr LazyMontgomeryModInt(const int64_t &b) : a(reduce(u64(b % mod + mod) * n2)){}; static constexpr u32 reduce(const u64 &b) { return (b + u64(u32(b) * u32(-r)) * mod) >> 32; } constexpr mint &operator+=(const mint &b) { if (i32(a += b.a - 2 * mod) < 0) a += 2 * mod; return *this; } constexpr mint &operator-=(const mint &b) { if (i32(a -= b.a) < 0) a += 2 * mod; return *this; } constexpr mint &operator*=(const mint &b) { a = reduce(u64(a) * b.a); return *this; } constexpr mint &operator/=(const mint &b) { *this *= b.inverse(); return *this; } constexpr mint operator+(const mint &b) const { return mint(*this) += b; } constexpr mint operator-(const mint &b) const { return mint(*this) -= b; } constexpr mint operator*(const mint &b) const { return mint(*this) *= b; } constexpr mint operator/(const mint &b) const { return mint(*this) /= b; } constexpr bool operator==(const mint &b) const { return (a >= mod ? a - mod : a) == (b.a >= mod ? b.a - mod : b.a); } constexpr bool operator!=(const mint &b) const { return (a >= mod ? a - mod : a) != (b.a >= mod ? b.a - mod : b.a); } constexpr mint operator-() const { return mint() - mint(*this); } constexpr mint operator+() const { return mint(*this); } constexpr mint pow(u64 n) const { mint ret(1), mul(*this); while (n > 0) { if (n & 1) ret *= mul; mul *= mul; n >>= 1; } return ret; } constexpr mint inverse() const { int x = get(), y = mod, u = 1, v = 0, t = 0, tmp = 0; while (y > 0) { t = x / y; x -= t * y, u -= t * v; tmp = x, x = y, y = tmp; tmp = u, u = v, v = tmp; } return mint{u}; } friend ostream &operator<<(ostream &os, const mint &b) { return os << b.get(); } friend istream &operator>>(istream &is, mint &b) { int64_t t; is >> t; b = LazyMontgomeryModInt<mod>(t); return (is); } constexpr u32 get() const { u32 ret = reduce(a); return ret >= mod ? ret - mod : ret; } static constexpr u32 get_mod() { return mod; } }; using MOD = StaticModular<i64, 1234567891>; using Mi = ModInt<MOD>; //using Mi = LazyMontgomeryModInt<1234567891>; void SolveOne(int test_id, IStream &in, OStream &out) { i32 N; i64 M; in >> N >> M; Vec<int> A(N); in >> A; int sum = 0; for(var a : A) { sum += a; } Debug(N); Debug(M); Debug(A); var create_dp = [&]() { return MDVecDef<Mi, 1>::Make(2 * sum + 1, Mi(0)); }; var dp = create_dp(); var print_dp = [&]() { DebugRun({ for(int i = 0; i < Size(dp); i++) { DebugFmtln("dp[%d] = %d", i, dp[i]); } }) }; dp[0] = 1; //Debug(dp); for(int bit = 0; (i64(1) << bit) <= M; bit++) { //Debug(bit); for(var a : A) { var next = create_dp(); for(int i = 0; i < Size(next); i++) { if(i + a < Size(next)) { next[i + a] += dp[i]; } next[i] += dp[i]; } dp = Move(next); // Debug(a); // Debug(dp); } //compact int current_bit = (M >> bit) & 1; var next = create_dp(); for(int i = current_bit; i < Size(dp); i += 2) { next[i / 2] = dp[i]; } dp = Move(next); //Debug(dp); } var ans = dp[0]; out << ans; } void SolveMulti(IStream &in, OStream &out) { //std::ifstream input("in"); int num_of_input = 1; //in >> num_of_input; for (int i = 0; i < num_of_input; i++) { //SolveOne(i + 1, input, out); SolveOne(i + 1, in, out); } } int main() { std::ios_base::sync_with_stdio(false); Stdin.tie(0); Stdout << std::setiosflags(std::ios::fixed); Stdout << std::setprecision(15); #ifdef STRESS stress::Stress(); #else SolveMulti(Stdin, Stdout); #endif return 0; }