結果

問題 No.137 貯金箱の焦り
ユーザー Dal TaoDal Tao
提出日時 2024-08-11 18:28:08
言語 C++23
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 4,110 ms / 5,000 ms
コード長 58,839 bytes
コンパイル時間 2,780 ms
コンパイル使用メモリ 193,344 KB
実行使用メモリ 57,416 KB
最終ジャッジ日時 2024-08-11 18:28:33
合計ジャッジ時間 24,807 ms
ジャッジサーバーID
(参考情報)
judge4 / judge5
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 8 ms
5,248 KB
testcase_01 AC 3 ms
5,376 KB
testcase_02 AC 22 ms
5,376 KB
testcase_03 AC 1 ms
5,376 KB
testcase_04 AC 142 ms
6,144 KB
testcase_05 AC 25 ms
5,376 KB
testcase_06 AC 65 ms
5,376 KB
testcase_07 AC 32 ms
5,376 KB
testcase_08 AC 33 ms
5,376 KB
testcase_09 AC 72 ms
5,376 KB
testcase_10 AC 33 ms
5,376 KB
testcase_11 AC 2 ms
5,376 KB
testcase_12 AC 4,110 ms
57,416 KB
testcase_13 AC 294 ms
9,856 KB
testcase_14 AC 1,924 ms
30,800 KB
testcase_15 AC 1,962 ms
31,372 KB
testcase_16 AC 1,925 ms
30,424 KB
testcase_17 AC 910 ms
17,252 KB
testcase_18 AC 1,898 ms
30,004 KB
testcase_19 AC 1,958 ms
31,228 KB
testcase_20 AC 88 ms
5,376 KB
testcase_21 AC 1,905 ms
28,336 KB
testcase_22 AC 430 ms
10,272 KB
testcase_23 AC 408 ms
10,204 KB
testcase_24 AC 883 ms
16,708 KB
testcase_25 AC 1,945 ms
28,668 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

//Timestamp: 2024-08-11 17:27:26
#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(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 < 0) {
      res -= MOD;
    }
    return res;
  }
  Self operator-(const Self &rhs) const {
    if(value >= rhs.value) {
      return value - rhs.value;
    } else {
      return value + MOD - rhs.value;
    }
  }
  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
#ifndef _builtin_clz
inline i32 _builtin_clz(u32 i) {
  // HD, Count leading 0's
  if (i <= 0) return i == 0 ? 32 : 0;
  int n = 31;
  if (i >= 1 << 16) {
    n -= 16;
    i >>= 16;
  }
  if (i >= 1 << 8) {
    n -= 8;
    i >>= 8;
  }
  if (i >= 1 << 4) {
    n -= 4;
    i >>= 4;
  }
  if (i >= 1 << 2) {
    n -= 2;
    i >>= 2;
  }
  return n - (i >> 1);
}
#endif
#ifndef _builtin_clzll
inline i32 _builtin_clzll(u64 i) {
  u32 x = u32(i >> 32);
  return x == 0 ? 32 + _builtin_clz((int)i) : _builtin_clz(x);
}
#endif
#ifndef _builtin_ctz
inline i32 _builtin_ctz(u32 i) {
  // HD, Figure 5-14
  int y;
  if (i == 0) return 32;
  int n = 31;
  y = i << 16;
  if (y != 0) {
    n = n - 16;
    i = y;
  }
  y = i << 8;
  if (y != 0) {
    n = n - 8;
    i = y;
  }
  y = i << 4;
  if (y != 0) {
    n = n - 4;
    i = y;
  }
  y = i << 2;
  if (y != 0) {
    n = n - 2;
    i = y;
  }
  return n - ((i << 1) >> 31);
}
#endif
#ifndef _builtin_ctzll
inline i32 _builtin_ctzll(u64 i) {
  // HD, Figure 5-14
  int x, y;
  if (i == 0) return 64;
  int n = 63;
  y = (int)i;
  if (y != 0) {
    n = n - 32;
    x = y;
  } else
    x = (int)(i >> 32);
  y = x << 16;
  if (y != 0) {
    n = n - 16;
    x = y;
  }
  y = x << 8;
  if (y != 0) {
    n = n - 8;
    x = y;
  }
  y = x << 4;
  if (y != 0) {
    n = n - 4;
    x = y;
  }
  y = x << 2;
  if (y != 0) {
    n = n - 2;
    x = y;
  }
  return n - ((x << 1) >> 31);
}
#endif
#ifndef _builtin_popcount
inline i32 _builtin_popcount(u32 i) {
  // HD, Figure 5-2
  i = i - ((i >> 1) & 0x55555555);
  i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
  i = (i + (i >> 4)) & 0x0f0f0f0f;
  i = i + (i >> 8);
  i = i + (i >> 16);
  return i & 0x3f;
}
#endif
#ifndef _builtin_popcountll
inline i32 _builtin_popcountll(u64 i) {
  // HD, Figure 5-2
  i = i - ((i >> 1) & 0x5555555555555555ll);
  i = (i & 0x3333333333333333ll) + ((i >> 2) & 0x3333333333333333ll);
  i = (i + (i >> 4)) & 0x0f0f0f0f0f0f0f0fll;
  i = i + (i >> 8);
  i = i + (i >> 16);
  i = i + (i >> 32);
  return (int)i & 0x7f;
}
#endif
namespace dalt {
inline i32 LeadingZeroNumber(u32 x) {
  if (x == 0) return 32;
  return _builtin_clz(x);
}
inline i32 LeadingZeroNumber(i32 x) { return LeadingZeroNumber(u32(x)); }
inline i32 LeadingZeroNumber(u64 x) {
  if (x == 0) return 64;
  return _builtin_clzll(x);
}
inline i32 LeadingZeroNumber(i64 x) { return LeadingZeroNumber(u64(x)); }
inline i32 TrailingZeroNumber(u32 x) {
  if (x == 0) return 32;
  return _builtin_ctz(x);
}
inline i32 TrailingZeroNumber(i32 x) { return TrailingZeroNumber(u32(x)); }
inline i32 TrailingZeroNumber(u64 x) {
  if (x == 0) return 64;
  return _builtin_ctzll(x);
}
inline i32 TrailingZeroNumber(i64 x) { return TrailingZeroNumber(u64(x)); }
inline i32 Log2Ceil(u32 x) {
  if (x == 0) {
    return 0;
  }
  return 32 - LeadingZeroNumber(x - 1);
}
inline i32 Log2Ceil(u64 x) {
  if (x == 0) {
    return 0;
  }
  return 64 - LeadingZeroNumber(x - 1);
}
inline i32 Log2Floor(u32 x) {
  if (x == 0) {
    return -1;
  }
  return 31 - LeadingZeroNumber(x);
}
inline i32 Log2Floor(u64 x) {
  if (x == 0) {
    return -1;
  }
  return 63 - LeadingZeroNumber(x);
}
inline i32 Log2Ceil(i32 x) { return Log2Ceil(u32(x)); }
inline i32 Log2Ceil(i64 x) { return Log2Ceil(u64(x)); }
inline i32 Log2Floor(i32 x) { return Log2Floor(u32(x)); }
inline i32 Log2Floor(i64 x) { return Log2Floor(u64(x)); }
inline i32 CountBit(u32 x) { return _builtin_popcount(x); }
inline i32 CountBit(i32 x) { return CountBit(u32(x)); }
inline i32 CountBit(u64 x) { return _builtin_popcountll(x); }
inline i32 CountBit(i64 x) { return CountBit(u64(x)); }
inline i32 HighestOneBitOffset(u32 x) { return Log2Floor(x); }
inline i32 HighestOneBitOffset(i32 x) { return HighestOneBitOffset(u32(x)); }
inline i32 HighestOneBitOffset(u64 x) { return Log2Floor(x); }
inline i32 HighestOneBitOffset(i64 x) { return HighestOneBitOffset(u64(x)); }
template <class T>
inline enable_if_t<is_integral_v<T>, T> LowestOneBit(T x) {
  return x & -x;
}
template <class T>
inline enable_if_t<is_integral_v<T>, T> HighestOneBit(T x) {
  if (x == 0) {
    return x;
  }
  return T(1) << HighestOneBitOffset(x);
}
template <class T>
inline enable_if_t<is_integral_v<T>, i32> LowestOneBitOffset(T x) {
  if (x == 0) {
    return -1;
  }
  return HighestOneBitOffset(LowestOneBit(x));
}
inline u32 HighestKOnes32(i32 k) {
  if (k == 0) {
    return 0;
  }
  return (~u32()) << (32 - k);
}
inline u64 HighestKOnes64(i32 k) {
  if (k == 0) {
    return 0;
  }
  return (~u64()) << (64 - k);
}
inline u32 LowestKOnes32(i32 k) {
  if (k == 0) {
    return 0;
  }
  return (~u32()) >> (32 - k);
}
inline u64 LowestKOnes64(i32 k) {
  if (k == 0) {
    return 0;
  }
  return (~u64()) >> (64 - k);
}
inline u64 IntervalOnes64(i32 l, i32 r) {
  if (l > r) {
    return 0;
  }
  u64 high = r < 63 ? (u64(-1) << r + 1) : 0;
  u64 low = u64(-1) << l;
  return high ^ low;
}
inline u32 IntervalOnes32(i32 l, i32 r) {
  if (l > r) {
    return 0;
  }
  u32 high = r < 31 ? (u32(-1) << r + 1) : 0;
  u32 low = u32(-1) << l;
  return high ^ low;
}
template <class T>
inline enable_if_t<is_integral_v<T>, i32> KthBit(T x, i32 k) {
  return (x >> k) & 1;
}
template <class T>
inline enable_if_t<is_integral_v<T>, T> SetBit(T x, i32 k) {
  return x | (T(1) << k);
}
template <class T>
inline enable_if_t<is_integral_v<T>, T> ClearBit(T x, i32 k) {
  return x & ~(T(1) << k);
}
}  // namespace dalt
namespace dalt {
static const u8 BitReverseTable[]{
    0,  128, 64, 192, 32, 160, 96,  224, 16, 144, 80, 208, 48, 176, 112, 240,
    8,  136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248,
    4,  132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244,
    12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252,
    2,  130, 66, 194, 34, 162, 98,  226, 18, 146, 82, 210, 50, 178, 114, 242,
    10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250,
    6,  134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246,
    14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254,
    1,  129, 65, 193, 33, 161, 97,  225, 17, 145, 81, 209, 49, 177, 113, 241,
    9,  137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
    5,  133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245,
    13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253,
    3,  131, 67, 195, 35, 163, 99,  227, 19, 147, 83, 211, 51, 179, 115, 243,
    11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251,
    7,  135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
    15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255};
inline u8 ReverseBit(u8 x) { return BitReverseTable[x]; }
inline i8 ReverseBit(i8 x) { return ReverseBit((u8)x); }
#define DefineReverseBit(bit, low)                                             \
  inline u##bit ReverseBit(u##bit x) {                                         \
    static const u##bit mask = (u##bit(1) << low) - 1;                         \
    return ReverseBit(u##low(x >> low)) |                                      \
           (u##bit(ReverseBit(u##low(x & mask))) << low);                      \
  }                                                                            \
  inline i##bit ReverseBit(i##bit x) { return ReverseBit(u##bit(x)); }
DefineReverseBit(16, 8);
DefineReverseBit(32, 16);
DefineReverseBit(64, 32);
#undef DefineReverseBit
} // namespace dalt
namespace dalt {
namespace poly {
MakeAnnotation(convolution)
}
} // namespace dalt
namespace dalt {
struct uint128 {
  u64 high, low;
  uint128(u64 _low = 0, u64 _high = 0) : high(_high), low(_low) {}
  using Self = uint128;
  CastToAllScalar(low);
  friend Self operator+(const Self& a, const Self& b) {
    Self ans(a.low + b.low, a.high + b.high);
    if (ans.low < a.low) {
      ans.high++;
    }
    return ans;
  }
  friend Self operator-(const Self& a, const Self& b) {
    u64 h = a.high - b.high;
    u64 l = a.low - b.low;
    if(a.low < b.low) {
      l = -l;
      h--;
    }
    return Self(l, h);
  }
  friend OStream& operator<<(OStream &os, const Self& x) {
    if(x.high) {
      os << x.high;
    }
    os << x.low;
    return os;
  }
  friend IStream& operator>>(IStream &is, Self& x) {
    x.high = 0;
    is >> x.low;
    return is;
  }
  friend Self operator*(const Self& a, const Self& b) {
    static u64 mask = ((u64(1) << 32) - 1);
    u64 all = a.low & mask;
    u64 bll = b.low & mask;
    u64 alh = a.low >> 32;
    u64 blh = b.low >> 32;
    Self ans(0, a.high * b.low + a.low * b.high + alh * blh + (all * blh >> 32) +
                 (alh * bll >> 32));
    ans += all * bll;
    ans += ((all * blh) & mask) << 32;
    ans += ((bll * alh) & mask) << 32;
    return ans;
  }
  Self& operator+=(const u64& rhs) {
    low += rhs;
    if (low < rhs) {
      high++;
    }
    return *this;
  }
  bool operator<(const Self& rhs) const {
    return MakePair(high, low) < MakePair(rhs.high, rhs.low);
  }
  ImplDefaultComparision(Self);
  ImplArithmeticAssignOperation(Self);
  //ImplArithmeticAssignOperation(Self);
  bool operator==(const Self& rhs) const {
    return high == rhs.high && low == rhs.low;
  }
  bool operator!=(const Self& rhs) const { return !(*this == rhs); }
  // x < 2 ^ 31
  u32 modular(u32 x) const {
    static u64 max = std::numeric_limits<u64>::max();
    u64 ans = low < x ? low : low % x;
    if (high > 0) {
      ans = ans + (high >= x ? high % x : high) * (max % x + 1);
      ans %= x;
    }
    return ans;
  }
  u32 operator%(u32 x) const {
    return modular(x);
  }
  Self operator/(u32 x) const {
    static const u32 ALL_ONE = -1;
    u64 y = high;
    u64 top = y / x;
    y = y - top * x;
    y = (y << 32) | (low >> 32);
    u64 low_high = y / x;
    y = y - low_high * x;
    y = (y << 32) | (low & ALL_ONE);
    u64 low_low = y / x;
    return Self(low_low | (low_high << 32), top);  
  }
};
using u128 = uint128;
}  // namespace dalt
namespace dalt {
namespace poly {
template <class T>
struct BruteForceConv {
  using Type = T;
  template <class Arg = T>
  static enable_if_t<is_same_v<Arg, T> &&
                         !(is_modint_v<T> && is_same_v<typename T::Type, i32>),
                     Vec<T>>
  conv(const Vec<T> &a, const Vec<T> &b) {
    int rank = Size(a) + Size(b) - 2; 
    Vec<T> c(rank + 1);
    for (int i = 0; i < Size(a); i++) {
      for (int j = 0; j < Size(b); j++) {
        c[i + j] += a[i] * b[j];
      }
    }
    return c;
  }
  template <class Arg = T>
  static enable_if_t<is_same_v<Arg, T> && is_modint_v<T> &&
                         is_same_v<typename T::Type, i32>,
                     Vec<T>>
  conv(const Vec<T> &a, const Vec<T> &b) {
    int rank = Size(a) + Size(b) - 2;
    Vec<u128> data(rank + 1);
    for(int i = 0; i < Size(a); i++) {
      for(int j = 0; j < Size(b); j++) {
        data[i + j] += u64(a[i].value) * b[j].value;
      }
    }
    Vec<T> ans(rank + 1);
    i32 modulus = T::modulus();
    for(int i = 0; i <= rank; i++) {
      ans[i] = data[i].modular(modulus);
    } 
    return ans;
  }
  static Vec<T> conv2(const Vec<T> &a) { return conv(a, a); }
  static Vec<T> inverse(Vec<T> p, i32 n) {
    Extend(p, n);
    auto dfs = [&](auto &dfs, i32 m) -> Vec<T> {
      if (m == 1) {
        return Vec<T>{T(1) / p[0]};
      }
      i32 prev_mod = (m + 1) / 2;
      auto C = dfs(dfs, prev_mod);
      auto AC = conv(p, m, C, prev_mod);
      AC.resize(m);
      for (int i = 0; i < m; i++) {
        AC[i] = T(0) - AC[i];
      }
      AC[0] = AC[0] + T(2);
      auto res = conv(C, AC);
      res.resize(m);
      return res;
    };
    auto ans = dfs(dfs, n);
    ans.resize(n);
    return ans;
  }
  static Array<Vec<T>, 2> div_and_rem(Vec<T> a, Vec<T> b) {
    Reverse(All(b));
    auto inv_first = T(1) / b[0];
    i32 n = Size(a);
    i32 m = Size(b);
    if (n < m) {
      return {Vec<T>{T(0)}, Vec<T>{Move(a)}};
    }
    Vec<T> divisor(n - m + 1);
    for (int i = n - 1; i >= m - 1; i++) {
      if (a[i] == T(0)) {
        continue;
      }
      T factor = a[i] * inv_first;
      divisor[i - (m - 1)] = factor;
      for (int j = 0; j < m; j++) {
        a[i - j] = a[i - j] - b[j] * factor;
      }
    }
    return Array<Vec<T>, 2>{Move(divisor), Move(a)};
  }
};
template<class T>
struct is_convolution<BruteForceConv<T>> {
  static const bool value = true;
};
}  // namespace poly
}  // namespace dalt
namespace dalt {
namespace poly {
template <class T>
Vec<T> CopyAndExtend(const Vec<T> &data, int n) {
  Vec<T> res;
  res.reserve(n);
  if (n <= Size(data)) {
    res.insert(res.begin(), data.begin(), data.begin() + n);
  } else {
    res.insert(res.begin(), All(data));
    res.resize(n);
  }
  return res;
}
template <class T>
void Normalize(Vec<T> &p) {
  while (!p.empty() && p.back() == T(0)) {
    p.pop_back();
  }
  if (p.empty()) {
    p.push_back(T(0));
  }
}
template <class T>
void Extend(Vec<T> &p, int cap) {
  while (Size(p) < cap) {
    p.push_back(T());
  }
}
template <class T>
Vec<T> DotMul(const Vec<T> &a, const Vec<T> &b) {
  int n = Min(Size(a), Size(b));
  Vec<T> ans(n);
  for (int i = 0; i < n; i++) {
    ans[i] = a[i] * b[i];
  }
  return ans;
}
template <class T>
void DotMulInplace(Vec<T> &a, const Vec<T> &b) {
  int n = Size(b);
  a.resize(n);
  for (int i = 0; i < n; i++) {
    a[i] = a[i] * b[i];
  }
}
template <class T>
void DotMulPlus(Vec<T> &a, const Vec<T> &b, Vec<T> &res) {
  int n = Min(Size(a), Size(b));
  for (int i = 0; i < n; i++) {
    res[i] = res[i] + a[i] * b[i];
  }
}
template <class T>
T Apply(const Vec<T> &a, T x) {
  T sum = 0;
  for (int i = Size(a) - 1; i >= 0; i--) {
    sum = sum * x + a[i];
  }
  return sum;
}
}  // namespace poly
}  // namespace dalt
namespace dalt {
namespace poly {
template <class F>
enable_if_t<is_floating_point_v<F>> fft(Vec<Complex<F>> &p, bool inv) {
  static const F PI = std::asin((long double)1) * 2;
  using cpx = Complex<F>;
  static Vec<Vec<cpx>> multi_levels(30);
  int m = Log2Ceil(Size(p));
  int n = 1 << m;
  Assert((1 << m) == Size(p));
  int shift = 32 - TrailingZeroNumber(n);
  for (int i = 1; i < n; i++) {
    int j = ReverseBit(i << shift);
    if (i < j) {
      Swap(p[i], p[j]);
    }
  }
  for (int d = 0; d < m; d++) {
    int s = 1 << d;
    int s2 = s << 1;
    auto &level = multi_levels[d];
    if (level.empty()) {
      // init
      level.resize(1 << d);
      for (int j = 0, s = 1 << d; j < s; j++) {
        level[j] = cpx(Cos(F(PI) / s * j), Sin(F(PI) / s * j));
      }
    }
    for (int i = 0; i < n; i += s2) {
      for (int j = 0; j < s; j++) {
        auto a = i + j;
        auto b = a + s;
        auto t = level[j] * p[b];
        p[b] = p[a] - t;
        p[a] = p[a] + t;
      }
    }
  }
  if (inv) {
    int i = 0;
    int j = 0;
    F tn = n;
    while (i <= j) {
      auto pj = p[j];
      p[j] = p[i] / tn;
      if (i != j) {
        p[i] = pj / tn;
      }
      i += 1;
      j = n - i;
    }
  }
}
template <class M, class F = f80>
struct FFTConv {
  static_assert(is_modint_v<M>);
  using cpx = Complex<F>;
  using mi = M;
  using Type = mi;
  static_assert(is_same_v<i32, typename M::Type>);
  static Vec<mi> conv(const Vec<mi> &a, const Vec<mi> &b) {
    if (Size(a) <= 20 || Size(b) <= 20) {
      return BruteForceConv<M>::conv(a, b);
    }
    if (&a == &b) {
      return conv2(a);
    }
    return conv(a, Size(a), b, Size(b));
  }
  static Vec<mi> conv(const Vec<mi> &a, int na, const Vec<mi> &b, int nb) {
    let rank_a = na - 1;
    let rank_b = nb - 1;
    i32 step = 15;
    i32 mask = (1 << step) - 1;
    let n = 1 << Log2Ceil(rank_a + rank_b + 1);
    Vec<cpx> a_cpx(n);
    Vec<cpx> b_cpx(n);
    for (int i = 0; i < na; i++) {
      let x = a[i].value;
      a_cpx[i] = cpx(x & mask, x >> step);
    }
    for (int i = 0; i < nb; i++) {
      let x = b[i].value;
      b_cpx[i] = cpx(x & mask, x >> step);
    }
    fft(a_cpx, false);
    fft(b_cpx, false);
    i32 i = 0;
    i32 j = 0;
    while (i <= j) {
      let ari = a_cpx[i].real();
      let aii = a_cpx[i].imag();
      let bri = b_cpx[i].real();
      let bii = b_cpx[i].imag();
      let arj = a_cpx[j].real();
      let aij = a_cpx[j].imag();
      let brj = b_cpx[j].real();
      let bij = b_cpx[j].imag();
      let a1r = (ari + arj) / 2;
      let a1i = (aii - aij) / 2;
      let a2r = (aii + aij) / 2;
      let a2i = (arj - ari) / 2;
      let b1r = (bri + brj) / 2;
      let b1i = (bii - bij) / 2;
      let b2r = (bii + bij) / 2;
      let b2i = (brj - bri) / 2;
      a_cpx[i] = cpx(a1r * b1r - a1i * b1i - a2r * b2i - a2i * b2r,
                     a1r * b1i + a1i * b1r + a2r * b2r - a2i * b2i);
      b_cpx[i] = cpx(a1r * b2r - a1i * b2i + a2r * b1r - a2i * b1i,
                     a1r * b2i + a1i * b2r + a2r * b1i + a2i * b1r);
      if (i != j) {
        let a1r = (arj + ari) / 2;
        let a1i = (aij - aii) / 2;
        let a2r = (aij + aii) / 2;
        let a2i = (ari - arj) / 2;
        let b1r = (brj + bri) / 2;
        let b1i = (bij - bii) / 2;
        let b2r = (bij + bii) / 2;
        let b2i = (bri - brj) / 2;
        a_cpx[j] = cpx(a1r * b1r - a1i * b1i - a2r * b2i - a2i * b2r,
                       a1r * b1i + a1i * b1r + a2r * b2r - a2i * b2i);
        b_cpx[j] = cpx(a1r * b2r - a1i * b2i + a2r * b1r - a2i * b1i,
                       a1r * b2i + a1i * b2r + a2r * b1i + a2i * b1r);
      }
      i += 1;
      j = n - i;
    }
    fft(a_cpx, true);
    fft(b_cpx, true);
    i64 modulus = M::modulus();
    Vec<mi> ans(n);
    for (int i = 0; i < n; i++) {
      i64 aa = Round(a_cpx[i].real());
      i64 bb = Round(b_cpx[i].real());
      i64 cc = Round(a_cpx[i].imag());
      ans[i] = (aa + (bb % modulus << 15) + (cc % modulus << 30)) % modulus;
    }
    return ans;
  }
  static Vec<mi> conv2(const Vec<mi> &p) {
    int na, nb;
    na = nb = Size(p);
    let rank_a = na - 1;
    let rank_b = nb - 1;
    i32 step = 15;
    i32 mask = (1 << step) - 1;
    let n = 1 << Log2Ceil(rank_a + rank_b + 1);
    Vec<cpx> a_cpx(n);
    for (int i = 0; i < na; i++) {
      let x = p[i].value;
      a_cpx[i] = cpx(x & mask, x >> step);
    }
    fft(a_cpx, false);
    auto b_cpx = a_cpx;
    i32 i = 0;
    i32 j = 0;
    while (i <= j) {
      let ari = a_cpx[i].real();
      let aii = a_cpx[i].imag();
      let bri = b_cpx[i].real();
      let bii = b_cpx[i].imag();
      let arj = a_cpx[j].real();
      let aij = a_cpx[j].imag();
      let brj = b_cpx[j].real();
      let bij = b_cpx[j].imag();
      let a1r = (ari + arj) / 2;
      let a1i = (aii - aij) / 2;
      let a2r = (aii + aij) / 2;
      let a2i = (arj - ari) / 2;
      let b1r = (bri + brj) / 2;
      let b1i = (bii - bij) / 2;
      let b2r = (bii + bij) / 2;
      let b2i = (brj - bri) / 2;
      a_cpx[i] = cpx(a1r * b1r - a1i * b1i - a2r * b2i - a2i * b2r,
                     a1r * b1i + a1i * b1r + a2r * b2r - a2i * b2i);
      b_cpx[i] = cpx(a1r * b2r - a1i * b2i + a2r * b1r - a2i * b1i,
                     a1r * b2i + a1i * b2r + a2r * b1i + a2i * b1r);
      if (i != j) {
        let a1r = (arj + ari) / 2;
        let a1i = (aij - aii) / 2;
        let a2r = (aij + aii) / 2;
        let a2i = (ari - arj) / 2;
        let b1r = (brj + bri) / 2;
        let b1i = (bij - bii) / 2;
        let b2r = (bij + bii) / 2;
        let b2i = (bri - brj) / 2;
        a_cpx[j] = cpx(a1r * b1r - a1i * b1i - a2r * b2i - a2i * b2r,
                       a1r * b1i + a1i * b1r + a2r * b2r - a2i * b2i);
        b_cpx[j] = cpx(a1r * b2r - a1i * b2i + a2r * b1r - a2i * b1i,
                       a1r * b2i + a1i * b2r + a2r * b1i + a2i * b1r);
      }
      i += 1;
      j = n - i;
    }
    fft(a_cpx, true);
    fft(b_cpx, true);
    i64 modulus = M::modulus();
    Vec<mi> ans(n);
    for (int i = 0; i < n; i++) {
      i64 aa = Round(a_cpx[i].real());
      i64 bb = Round(b_cpx[i].real());
      i64 cc = Round(a_cpx[i].imag());
      ans[i] = (aa + (bb % modulus << 15) + (cc % modulus << 30)) % modulus;
    }
    return ans;
  }
  static Vec<mi> inverse(Vec<mi> p, i32 n) {
    Extend(p, n);
    auto dfs = [&](auto &dfs, i32 m) -> Vec<mi> {
      if (m == 1) {
        return Vec<mi>{mi(1) / p[0]};
      }
      i32 prev_mod = (m + 1) / 2;
      auto C = dfs(dfs, prev_mod);
      auto AC = conv(p, m, C, prev_mod);
      AC.resize(m);
      for (int i = 0; i < m; i++) {
        AC[i] = mi(0) - AC[i];
      }
      AC[0] = AC[0] + mi(2);
      auto res = conv(C, AC);
      res.resize(m);
      return res;
    };
    auto ans = dfs(dfs, n);
    ans.resize(n);
    return ans;
  }
};
template <class F, class M>
struct is_convolution<FFTConv<F, M>> {
  static const bool value = true;
};
}  // namespace poly
}  // namespace dalt
namespace dalt {
namespace math {
template <class T>
Vec<T> InverseBatch(Vec<T> batch) {
  int n = int(batch.size());
  Vec<T> origin = batch;
  T fact = 1;
  for (int i = 0; i < n; i++) {
    if (origin[i] == T(0)) {
      continue;
    }
    T val = batch[i];
    batch[i] = fact;
    fact = fact * val;
  }
  T inv_fact = T(1) / fact;
  for (int i = n - 1; i >= 0; i--) {
    if (origin[i] == T(0)) {
      continue;
    }
    batch[i] = batch[i] * inv_fact;
    inv_fact = inv_fact * origin[i];
  }
  return batch;
}
}  // namespace math
}  // namespace dalt
namespace dalt {
namespace math {
template <class T>
struct Combination {
  static_assert(is_modint_v<T>);
  using Modular = typename T::Modular;
  Vec<T> fact;
  Vec<T> inv_fact;
  Combination(int cap) {
    cap += 1;
    fact.resize(cap);
    inv_fact.resize(cap);
    fact[0] = T(1);
    for (int i = 1; i < cap; i++) {
      T v = T(i);
      if (v != T(0)) {
        fact[i] = fact[i - 1] * v;
      } else {
        fact[i] = fact[i];
      }
    }
    T inv = T(1) / fact.back();
    for (int i = cap - 1; i >= 0; i--) {
      T v = T(i);
      inv_fact[i] = inv;
      if (v != T(0)) {
        inv = inv * T(i);
      }
    }
  }
  T inverse(int x) { return inv_fact[x] * fact[x - 1]; }
  T combination(int a, int b) {
    if (a < b || b < 0) {
      return T(0);
    }
    return fact[a] * inv_fact[b] * inv_fact[a - b];
  }
  template <class E>
  T combination_lucas(E a, E b) {
    if (a < b || b < 0) {
      return T(0);
    }
    if (a < Modular::modulus) {
      return fact[a] * inv_fact[b] * inv_fact[a - b];
    } else {
      return combination(a % Modular::modulus, b % Modular::modulus) *
             combination_lucas(a / Modular::modulus, b / Modular::modulus);
    }
  }
};
}  // namespace math
}  // namespace dalt
namespace dalt {
namespace poly {
const static int POLY_FAST_MAGIC_THRESHOLD = 64;
MakeAnnotation(polynomial);
template <class Conv>
struct Polynomial {
  static_assert(is_convolution_v<Conv>);
  using T = typename Conv::Type;
  using Type = T;
  using Seq = Vec<T>;
  using Self = Polynomial<Conv>;
  Seq data;
  Polynomial(T v = T(0)): Polynomial(Vec<T>{v}) {}
  Polynomial(Vec<T> _data) : data(Move(_data)) { Normalize(data); }
  T operator()(T x) const { return Apply(data, x); }
  T apply(T x) const { return (*this)(x); }
  Self integral() const {
    let rank = this->rank();
    Vec<T> range(rank + 1);
    for (int i = 0; i <= rank; i++) {
      range[i] = i + 1;
    }
    let inv = math::InverseBatch(move(range));
    Vec<T> ans(rank + 2);
    for (int i = 0; i <= rank; i++) {
      ans[i + 1] = inv[i] * data[i];
    }
    return Self(ans);
  }
  Self differential() const {
    Vec<T> ans(rank());
    for (int i = 1; i <= Size(ans); i++) {
      ans[i - 1] = data[i] * T(i);
    }
    return Self(ans);
  }
  void self_modular(i32 n) {
    if(data.size() >= n) {
      data.resize(n);
      Normalize(data);
    }
  }
  Self modular(i32 n) const { return Self(CopyAndExtend(data, n)); }
  static Self of(T val) { return Self(Vec<T>{val}); }
  Self ln(i32 n) const {
    Assert(data[0] == T(1));
    let diff = differential().modular(n);
    let inv = inverse(n);
    return (diff * inv).integral().modular(n);
  }
  Self exp(i32 n) const {
    if (n == 0) {
      return Self::of(T(0));
    }
    auto dfs = [&](auto &dfs, i32 n) -> Self {
      if (n == 1) {
        return Self::of(T(1));
      }
      let ans = dfs(dfs, (n + 1) / 2);
      let ln = this->modular(n) - ans.ln(n);
      ln.data[0] = ln.data[0] + T(1);
      return (ans * ln).modular(n);
    };
    return dfs(dfs, n);
  }
  int rank() const { return Size(data) - 1; }
  Self operator*(const Self &rhs) const {
    const Self &lhs = *this;
    // if (Min(lhs.rank(), rhs.rank()) < POLY_FAST_MAGIC_THRESHOLD) {
    //   return Self(BruteForceConv<T>::conv(lhs.data, rhs.data));
    // }
    return Self(Conv::conv(lhs.data, rhs.data));
  }
  Self operator*(const T &rhs) const {
    Vec<T> res = data;
    for (int i = 0; i < Size(res); i++) {
      res[i] = res[i] * rhs;
    }
    return Self(res);
  }
  Self &operator*=(const T &rhs) {
    for (int i = 0; i < Size(data); i++) {
      data[i] = data[i] * rhs;
    }
    Normalize(data);
    return *this;
  }
  Self operator+(const T &rhs) const {
    Vec<T> res = data;
    res[0] = res[0] + rhs;
    return Self(res);
  }
  Self operator+=(const T &rhs) const {
    data[0] = data[0] + rhs;
    Normalize(data);
    return data;
  }
  Self operator-(const T &rhs) const {
    Vec<T> res = data;
    res[0] = res[0] - rhs;
    return Self(res);
  }
  Self operator-=(const T &rhs) const {
    data[0] = data[0] - rhs;
    Normalize(data);
    return data;
  }
  Self operator>>(i32 n) const {
    if (n < 0) {
      return *this << -n;
    }
    if (*this == Self::of(T(0))) {
      return Self::of(T(0));
    }
    Vec<T> res(Size(data) + n);
    for (int i = 0; i < Size(data); i++) {
      res[i + n] = data[i];
    }
    return Self(res);
  }
  Self operator<<(i32 n) const {
    if (n < 0) {
      return *this >> -n;
    }
    if (Size(data) < n) {
      return Self::of(T(0));
    }
    Vec<T> res(Size(data) - n);
    for (int i = 0; i < Size(res); i++) {
      res[i] = data[i + n];
    }
    return Self(res);
  }
  Self operator/(const Self &rhs) const {
    auto a = data;
    auto b = rhs.data;
    if (a.size() < b.size()) {
      return Self::of(T(0));
    }
    if (b.size() <= POLY_FAST_MAGIC_THRESHOLD) {
      return BruteForceConv<T>::div_and_rem(Move(a), Move(b))[0];
    }
    Reverse(All(a));
    Reverse(All(b));
    i32 c_rank = Size(a) - Size(b);
    i32 proper_len = 1 << Log2Ceil(c_rank * 2 + 1);
    a.resize(proper_len);
    b.resize(proper_len);
    Vec<T> c = Conv::inverse(move(b), c_rank + 1);
    Vec<T> prod = Conv::conv(move(a), move(c));
    prod.resize(c_rank + 1);
    Reverse(All(prod));
    return Self(prod);
  }
  Self operator%(const Self &rhs) const {
    if (Min(rank(), rhs.rank()) < POLY_FAST_MAGIC_THRESHOLD) {
      return BruteForceConv<T>::div_and_rem(data, rhs.data)[1];
    }
    return *this - (*this / rhs) * rhs;
  }
  //return this(x + s)
  Self shift(T s) const {
    int r = rank();
    var comb = math::Combination<T>(r + 1);
    Vec<T> A(r + 1), B(r + 1);
    T s_pow = 1;
    for(int i = 0; i <= r; i++, s_pow *= s) {
      A[i] = data[i] * comb.fact[i];
      B[i] = s_pow * comb.inv_fact[i];
    }
    var C = Self(Move(A)).delta_convolution(Self(Move(B)));
    for(int i = 0; i <= C.rank(); i++) {
      C.data[i] *= comb.inv_fact[i];
    }
    Normalize(C.data); 
    return C;
  }
  Self operator+(const Self &rhs) const {
    const Self &lhs = *this;
    int n = Size(lhs.data);
    int m = Size(rhs.data);
    Vec<T> res(Max(n, m));
    for (int i = 0; i < n; i++) {
      res[i] = lhs.data[i];
    }
    for (int i = 0; i < m; i++) {
      res[i] = res[i] + rhs.data[i];
    }
    return Self(move(res));
  }
  Self operator-(const Self &rhs) const {
    const Self &lhs = *this;
    int n = Size(lhs.data);
    int m = Size(rhs.data);
    Vec<T> res(Max(n, m));
    for (int i = 0; i < n; i++) {
      res[i] = lhs.data[i];
    }
    for (int i = 0; i < m; i++) {
      res[i] = res[i] - rhs.data[i];
    }
    return Self(move(res));
  }
  T operator[](int index) const {
    return get(index);
  }
  T get(int index) const {
    if (index < Size(data)) {
      return data[index];
    }
    return T(0);
  }
  bool operator==(const_ref(Self) rhs) const { return data == rhs.data; }
  bool operator!=(const_ref(Self) rhs) const { return !(*this == rhs); }
  Vec<T> to_vec() const { return data; }
  Self inverse(int n) const { return Self(Conv::inverse(data, n)); }
  static Self mulmod(const Self &a, const Self &b, int mod) {
    return (a * b).modular(mod);
  }
  //O(n ln n ln n)
  Self powmod_binary_lift(i64 n, i32 mod) const {
    if (n == 0) {
      return Self::of(T(1)).modular(mod);
    }
    Self res = powmod_binary_lift(n / 2, mod);
    res = (res * res).modular(mod);
    if (n % 2 == 1) {
      res = (res * *this).modular(mod);
    }
    return res;
  }
  //O(n ln n)
  Self powmod_fast(i32 n_mod_modulus, i32 n_mod_phi, i64 estimate,
                   i32 mod) const {
    static_assert(is_modint_v<T>);
    static_assert(is_same_v<i32, typename T::Type>);
    if (estimate == 0) {
      return Self::of(T(1)).modular(mod);
    }
    if (*this == Self::of(T(0))) {
      return *this;
    }
    i32 k = 0;
    while (data[k] == T(0)) {
      k++;
    }
    if (MulLimit<i64>(k, estimate, mod) >= mod) {
      return Self::of(T(0));
    }
    auto expln = [&](const Self &p, i32 n_mod_modulus, i32 mod) -> Self {
      return (p.ln(mod) *= T(n_mod_modulus)).exp(mod);
    };
    auto expln_ext = [&](Self p, i32 n_mod_modulus, i32 n_mod_phi,
                         i32 mod) -> Self {
      T val = p[0];
      T inv = T(1) / p[0];
      p *= inv;
      Self res = expln(p, n_mod_modulus, mod);
      res *= PowBinaryLift(val, n_mod_phi);
      return res;
    };
    if (k == 0) {
      return expln_ext(*this, n_mod_modulus, n_mod_phi, mod);
    }
    Self trim = (*this) << k;
    Self res = expln_ext(Move(trim), n_mod_modulus, n_mod_phi, mod);
    return (res >> k * estimate).modular(mod);
  }
  static Self product(const Vec<Self> &data) {
    if (data.empty()) {
      return Self(Vec<T>{Type(1)});
    }
    auto dfs = [&](auto &dfs, int l, int r) {
      if (l == r) {
        return data[l];
      }
      int m = (l + r) / 2;
      return dfs(dfs, l, m) * dfs(dfs, m + 1, r);
    };
    return dfs(dfs, 0, Size(data) - 1);
  }
  //ret[i] = \sum_{j} this[i + j] * rhs[j]
  Self delta_convolution(const Self& rhs) const {
    Vec<T> lhs = data;
    Reverse(All(lhs));
    auto ans = Conv::conv(lhs, rhs.data);
    ans.resize(Size(lhs));
    Reverse(All(ans));
    return Self(Move(ans));
  }
};
AssignAnnotationTemplate(Polynomial, polynomial, class);
}  // namespace poly
}  // namespace dalt
namespace dalt {
template <class T, class C>
Indexer<T> MakeIndexer(const C &data) {
  return [&](auto i) -> T { return data[i]; };
}
template <class T, class C>
Indexer<T> MakeReverseIndexer(const C &data) {
  return [&](auto i) -> T { return data[Size(data) - 1 - i]; };
}
template <class T>
Vec<T> ExpandIndexer(int n, const Indexer<T> &indexer) {
  Vec<T> ans;
  ans.reserve(n);
  for (int i = 0; i < n; i++) {
    ans.push_back(indexer(i));
  }
  return ans;
}
Indexer<i32> SelfIndexer() {
  return [](auto i) { return i; };
}
template <class T>
Indexer<T> ConstantIndexer(const T &val) {
  return [=](auto i) { return val; };
}
template <class A, class B>
Mapper<A, B> ConstructorMapper() {
  return [&](auto a) { return B(a); };
}
template <class T>
Adder<T> NaturalAdder() {
  return [](auto a, auto b) { return a + b; };
}
template <class A, class B, class C>
constexpr Adder<A, B, C> EmptyAdder() {
  return [](auto a, auto b) { return C(); };
}
template <class A, class B = A>
constexpr Adder<A, B, A> ReturnLeftAdder() {
  return [](auto a, auto b) { return a; };
}
template <class A, class B = A>
constexpr Adder<A, B, B> ReturnRightAdder() {
  return [](auto a, auto b) { return b; };
}
template <class T>
Indexer<int> BinaryIndexer(const T& val) {
  return [=](int i) {return int((val >> i) & 1);};
}
template <class T>
Indexer<int> ReverseIndexer(int n, Indexer<T> indexer) {
  return [=](int i) {return indexer(n - 1 - i);};
}
Vec<int> MakeIndexVec(int n) {
  Vec<int> ans(n);
  for(int i = 0; i < n; i++) ans[i] = i;
  return ans;
}
}  // namespace dalt
namespace dalt {
namespace poly {
// Bostan-Mori Algorithm
// [x^k] P/Q 
// time complexity: O(M(Poly) n) where M(Poly) is the time taken to perform polynomial mutiplication
// consider from last bit to first bit (lower bit to higher bit), n - 1 means the lowest bit
template <class Poly>
typename Poly::Type KthTermOfInversePolynomial(int n,
                                               const Indexer<int> &bit_indexer,
                                               const Poly &P, const Poly &Q) {
  static_assert(is_polynomial_v<Poly>);
  using T = typename Poly::Type;
  if (n == 0) { return P[0] / Q[0]; }
  auto bit = bit_indexer(n - 1);
  //assert(P.rank() <= 1 && Q.rank() <= 1);
  Vec<T> neg_Q_data = Q.data;
  for (int i = 1; i < Size(neg_Q_data); i += 2) {
    neg_Q_data[i] = T(0) - neg_Q_data[i];
  }
  Poly neg_Q(Move(neg_Q_data));
  let AB = P * neg_Q;
  let QQ = Q * neg_Q;
  Vec<T> A;
  Vec<T> C;
  A.reserve((AB.rank() + 1 + 1) / 2);
  C.reserve((QQ.rank() + 1 + 1) / 2);
  for (int i = bit; i <= AB.rank(); i += 2) {
    A.push_back(AB[i]);
  }
  for (int i = 0; i <= QQ.rank(); i += 2) {
    C.push_back(QQ[i]);
  }
  return KthTermOfInversePolynomial(n - 1, bit_indexer, Poly(Move(A)),
                                    Poly(Move(C)));
}
}  // namespace poly
}  // namespace dalt
using namespace std;
using MOD = StaticModular<i32, 1234567891>;
using Mi = ModInt<MOD>;
//using Mi = ModInt998244353;
using Conv = poly::FFTConv<Mi>;
using Poly = poly::Polynomial<Conv>;
void SolveOne(int test_id, IStream &in, OStream &out) {
  i32 N;
  i64 M;
  in >> N >> M;
  Vec<int> A(N);
  in >> A;
  Vec<Poly> ps(N);
  for(int i = 0; i < N; i++) {
    Vec<Mi> data(A[i] + 1);
    data[0] = 1;
    data[A[i]] = -1;
    ps[i] = Move(data);
  }
  var prod = Poly::product(ps);
  Vec<int> bits;
  {
    i64 M2 = M;
    while(M2 > 0) {
      bits.push_back(M2 % 2);
      M2 /= 2;
    }
    Reverse(All(bits));
  }
  var ans = poly::KthTermOfInversePolynomial<Poly>(Size(bits), [&](int i) {return bits[i];}, Poly(1), prod);
  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;
}
0