結果

問題 No.3538 Not First Place
コンテスト
ユーザー jastaway
提出日時 2026-05-08 23:46:39
言語 C++23
(gcc 15.2.0 + boost 1.89.0)
コンパイル:
g++-15 -O2 -lm -std=c++23 -Wuninitialized -DONLINE_JUDGE -o a.out _filename_
実行:
./a.out
結果
AC  
実行時間 411 ms / 5,000 ms
コード長 55,463 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 7,133 ms
コンパイル使用メモリ 438,476 KB
実行使用メモリ 67,328 KB
最終ジャッジ日時 2026-05-08 23:46:55
合計ジャッジ時間 10,950 ms
ジャッジサーバーID
(参考情報)
judge1_1 / judge2_1
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 2
other AC * 26
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

#ifdef _DEBUG
#define _GLIBCXX_DEBUG
#endif
#include <bits/stdc++.h>
using namespace std;
#include <atcoder/all>
using namespace atcoder;
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/tag_and_trait.hpp>
#include <ext/rope>
using namespace __gnu_pbds;
template<class T> using gset = tree<T,null_type,less<T>,rb_tree_tag,tree_order_statistics_node_update>;
template<class T, class U> using gmap = tree<T,U,less<T>,rb_tree_tag,tree_order_statistics_node_update>;
template<class T, class U> using ghmap = gp_hash_table<T, U>;
// #include <boost/rational.hpp>
// using namespace boost;
// using rat = rational<long long int>;
using mint = modint998244353;
// using mint = modint1000000007;
// using mint = modint;
using ll = long long;
using lll = __int128_t;
using ld = long double;
using ull = uint64_t;
using pll = pair<ll, ll>;
using vll = vector<ll>;
using vvll = vector<vll>;
using vvvll = vector<vvll>;
using vpll = vector<pll>;
using vvpll = vector<vpll>;
using vm = vector<mint>;
using vvm = vector<vm>;
using vvvm = vector<vvm>;
using vstr = vector<string>;
#define v(T) vector<T>
#define vv(T) vector<vector<T>>
#define vvv(T) vector<vector<vector<T>>>
#define vvvv(T) vector<vector<vector<vector<T>>>>

template<int M> istream &operator>>(istream &is, static_modint<M> &a){ll tmp; is >> tmp; a = tmp; return is;}
template<int M> ostream &operator<<(ostream &os, const static_modint<M> &a){ os << a.val(); return os; }
template<int M> istream &operator>>(istream &is, dynamic_modint<M> &a){ll tmp; is >> tmp; a = tmp; return is;}
template<int M> ostream &operator<<(ostream &os, const dynamic_modint<M> &a){ os << a.val(); return os; }
string to_string(const __int128_t &a) { if (a == 0) return "0"; string s = ""; __int128_t num = a; bool is_negative = false; if (num < 0) { is_negative = true; num = -num; } while (num > 0) { s += '0' + (num % 10); num /= 10; } if (is_negative) s += '-'; reverse(s.begin(), s.end()); return s; }
istream &operator>>(istream &is, __int128_t &a){ string s; is >> s; a = 0; for(char c : s) { if(isdigit(c)) {a = a*10 + (c - '0'); }  } if(s[0]=='-'){ a *= -1; } return is; }
ostream &operator<<(ostream &os, const __int128_t &a){ os << to_string(a); return os; }
template<class T, class U> istream &operator>>(istream &is, pair<T, U> &p) { is >> p.first >> p.second; return is; }
template<class T, class U> ostream &operator<<(ostream &os, const pair<T, U> &p) { if(&os == &std::cerr) { os << "(" << p.first << ", " << p.second << ")"; } else { os << p.first << " " << p.second; } return os; }
template<class T> istream &operator>>(istream &is, vector<T> &vec){ for(T &e : vec){is >> e;} return is; }
template<class T> ostream &operator<<(ostream &os, const vector<T> &vec) { for(int i = 0; i < (int)vec.size(); i++) { os << vec[i] << (i + 1 != (int)vec.size() ? " " : ""); } return os; }
template<class T> istream &operator>>(istream &is, deque<T> &vec){ for(T &e : vec){is >> e;} return is; }
template<class T> ostream &operator<<(ostream &os, const deque<T> &vec) { for(int i = 0; i < (int)vec.size(); i++) { os << vec[i] << (i + 1 != (int)vec.size() ? " " : ""); } return os; }
template<class T> ostream &operator<<(ostream &os, const set<T> &vec) { for(auto itr = vec.begin(); itr != vec.end(); itr++) { os << (itr != vec.begin() ? " " : "") << (*itr); } return os; }
template<class T> ostream &operator<<(ostream &os, const unordered_set<T> &vec) { for(auto itr = vec.begin(); itr != vec.end(); itr++) { os << (itr != vec.begin() ? " " : "") << (*itr); } return os; }
template<class T, class U> ostream &operator<<(ostream &os, const map<T, U> &vec) { for(auto itr = vec.begin(); itr != vec.end(); itr++) { os << (itr != vec.begin() ? " " : "") << (*itr); } return os; }
template<class T, class U> ostream &operator<<(ostream &os, const unordered_map<T, U> &vec) { for(auto itr = vec.begin(); itr != vec.end(); itr++) { os << (itr != vec.begin() ? " " : "") << (*itr); } return os; }

template <class Tuple, size_t... Is> void read_tuple(istream& is, Tuple& t, index_sequence<Is...>) { ((is >> std::get<Is>(t)), ...); }
template <class... Ts> istream& operator>>(istream& is, tuple<Ts...>& t) { read_tuple(is, t, index_sequence_for<Ts...>{}); return is; }
template <class Tuple, size_t... Is> void print_tuple(ostream& os, const Tuple& t, index_sequence<Is...>) { ((os << (Is == 0 ? "" : (&os == &std::cerr ? ", " : " ")) << std::get<Is>(t)), ...); }
template <class... Ts> ostream& operator<<(ostream& os, const tuple<Ts...>& t) { if(&os == &std::cerr) { os << "("; } print_tuple(os, t, index_sequence_for<Ts...>{}); if(&os == &std::cerr) { os << ")"; } return os; }

#ifdef _DEBUG
template <typename... Args>
void debug_out(Args... args) { ((std::cerr << " " << args), ...); std::cerr << "\n"; }
#define debug(...) do { \
    std::cerr << "[" << #__VA_ARGS__ << "]:"; \
    debug_out(__VA_ARGS__); \
} while(0)
#else
#define debug(...) (void)0
#endif

template <class... T> constexpr auto min (T... a) { return min(initializer_list<common_type_t<T...>>{a...}); }
template <class... T> constexpr auto max (T... a) { return max(initializer_list<common_type_t<T...>>{a...}); }
template<class T> using pqg = priority_queue<T, vector<T>, greater<T>>;
template<class T> T opmin(T x, T y) { return min(x, y); }
template<class T> T einf() { return numeric_limits<T>::max()/2; }
template<class T> T opmax(T x, T y) { return max(x, y); }
template<class T> T eminf() { return numeric_limits<T>::min()/2; }
template<class T> T opsum(T x, T y) { return x + y; }
template<class T> T ezero() { return (T)0; }
template<class T> using minseg = segtree<T, opmin<T>, einf<T>>;
template<class T> using maxseg = segtree<T, opmax<T>, eminf<T>>;
template<class T> using sumseg = segtree<T, opsum<T>, ezero<T>>;
// template<class T> struct v : vector<T> { using vector<T> :: vector; };
// template<class T> struct vv : vector<v<T>> { using vector<v<T>> :: vector; };
// template<class T> struct vvv : vector<vv<T>> { using vector<vv<T>> :: vector; };
template<class T, class U> inline bool chmin(T& a, U b) {if(a > b){a = b; return true;} else {return false;}};
template<class T, class U> inline bool chmax(T& a, U b) {if(a < b){a = b; return true;} else {return false;}};
template<class T> T dist_sq(const pair<T, T> &x, const pair<T, T> &y){return (x.first-y.first)*(x.first-y.first)+(x.second-y.second)*(x.second-y.second);}
template<class T> T cross_product(const pair<T, T> &x, const pair<T, T> &y){return x.first * y.second - x.second * y.first;}
template <typename T> struct Reverser {
    T& t;
    auto begin() const { return std::rbegin(t); }
    auto end() const { return std::rend(t); }
};
template <typename T> Reverser<T> reversed(T& t) { return {t}; }
template <typename T> Reverser<const T> reversed(const T& t) { return {t}; }
// #define rep(i,n) for(ll i = 0; i < (ll)(n); i++)
#define _GET5(_1,_2,_3,_4,NAME,...) NAME
#define _rep1(i, n)  for(long long i=0;i<(long long)(n);i++)
#define _rep2(i,k,n) for(long long i=(long long)(k);i<(long long)(n);i++)
#define _rep3(i,k,n,s) for(long long i=(long long)(k);i<(long long)(n);i+=(s))
#define rep(...) _GET5(__VA_ARGS__, _rep3, _rep2, _rep1)(__VA_ARGS__)
#define _rrep1(i, n)  for(long long i=(long long)(n) - 1;i>=0;i--)
#define _rrep2(i,k,n) for(long long i=(long long)(n)-1;i>=(long long)(k);i--)
#define _rrep3(i,k,n,s) for(long long i=(long long)(n);i>=(long long)(k);i-=(s))
#define rrep(...) _GET5(__VA_ARGS__, _rrep3, _rrep2, _rrep1)(__VA_ARGS__)
#define repr(i,n) for(ll i = (ll)(n) - 1; i >= 0; i--)
#define REP(i, l, r) for(ll i = (ll)l; i <= (ll)(r); i++)
#define REPR(i, l, r) for(ll i = (ll)r; i >= (ll)(l); i--)
const ll inf = (1 << 30);
const ll INF = (1LL << 60);
const vector<pair<ll, ll>> DIJ = {{1, 0}, {0, -1}, {-1, 0}, {0, 1}};
void out(){cout<<'\n';}
template<class T, class... Ts> void out(const T& a, const Ts&... b){ cout<<a; (cout<<... << (cout << ' ', b)); cout << '\n';}
void outf(){cout<<endl;}
template<class T, class... Ts> void outf(const T& a, const Ts&... b){ cout<<a; (cout<<... << (cout << ' ', b)); cout << endl;}
template<class T, class U> void outp(pair<T, U> a){ out((a).first, (a).second); }
template<class T, class U> void outpf(pair<T, U> a){ outf((a).first, (a).second); }
template<class T> void outv(T a){rep(i, (a).size()){ cout << (a)[i] << " "; } cout << endl;}
template<class T> void outvL(T a){rep(i, (a).size()){out((a)[i]);} cout << flush; }
// template<class T> void outvv(T a){rep(i, a.size()){ rep(j, a.at(i).size()){cout << a.at(i).at(j) << " "; } cout << endl; }}
// template<class T> void outvp(T a){rep(i, a.size()){ out2(a.at(i).first, a.at(i).second); }}
void setpre(int a){cout << fixed << setprecision(a);}
#define outN cout << "No\n"
#define outY cout << "Yes\n"
void outYN(bool flag) { cout << (flag ? "Yes\n" : "No\n"); }
#define dame(...) {outf(__VA_ARGS__);return 0;}

template<class... T> void read(T&... a){(cin >> ... >> a);}
#define readll(...) ll __VA_ARGS__; read(__VA_ARGS__)
#define readvll(a, n) vector<ll> a(n); read(a)
#define readvvll(a, n, m) vector<vector<ll>> a(n, vector<ll>(m)); read(a)
#define readvstr(a, n) vector<string> a(n); read(a)
#define readvt(type, a, n) vector<type> a(n); read(a)
#define readvll2(a, b, n) vector<ll> a(n), b(n); for(int lopi = 0; lopi < (int)(n); lopi++) cin >> (a)[lopi] >> (b)[lopi]
#define readvll3(a, b, c, n) vector<ll> a(n), b(n), c(n); for(int lopi = 0; lopi < (int)(n); lopi++) cin >> (a)[lopi] >> (b)[lopi] >> (c)[lopi]
#define readstr(...) string __VA_ARGS__; read(__VA_ARGS__)
#define readundirG(G, N, M) G = vvll(N); rep(lopi, M) {ll a, b; cin >> a >> b; G[a-1].push_back(b-1); G[b-1].push_back(a-1);}
#define readdirG(G, N, M) G = vvll(N); rep(lopi, M) {ll a, b; cin >> a >> b; G[a-1].push_back(b-1);}
#define readundirwghG(G, N, M) G = vv(pll)(N); rep(lopi, M) {ll a, b, c; cin >> a >> b >> c; G[a-1].emplace_back(b-1,c); G[b-1].emplace_back(a-1, c);}
#define readdirwghG(G, N, M) G = vv(pll)(N); rep(lopi, M) {ll a, b, c; cin >> a >> b >> c; G[a-1].emplace_back(b-1, c);}

#define All(a) (a).begin(), (a).end()
#define all(a) begin(a), end(a)
template<class T> inline void sortr(T& a){ sort((a).rbegin(), (a).rend()); }
template<class T> inline vector<int> argsort(T V, bool rev = false){vector<int> res(V.size()); iota(res.begin(), res.end(), 0); sort(res.begin(), res.end(), [&](int x, int y){if(!rev){return V[x] < V[y];}else{return V[x] > V[y];}}); return res;}
template<class T, class U> inline void sort_by_idx(T& V, vector<U>& I){assert(V.size() == I.size()); T tmpv = V; for(int loopi = 0; loopi < (int)I.size(); loopi++){V[loopi] = tmpv[I.at(loopi)];}}
template<class T, class U> inline void sortp(vector<T>& v1, vector<U>& v2, bool rev1 = false, int rev2 = false){assert(v1.size() == v2.size()); vector<int> I(v1.size()); iota(I.begin(), I.end(), 0); sort(I.begin(), I.end(), [&](const int x, const int y){if(v1[x] != v1[y]){return (bool)(rev1 ^ (v1[x] < v1[y]));}else{if(v2[x]==v2[y]){return false;} return (bool)(rev2 ^ (v2[x] < v2[y]));}}); sort_by_idx(v1, I); sort_by_idx(v2, I);}
template<class T> T POW(T x, ll n) {T ret = 1; while(n > 0){if(n & 1) ret *= x; x *= x; n >>= 1;} return ret;}
ll powll(ll x, ll n){ll ret = 1; while(n > 0){if(n & 1) ret *= x; x *= x; n >>= 1;} return ret;}
ll modpow(ll a,ll b,ll modd){ll res=1;a%=modd;while(b){if(b&1)res=res*a%modd;a=a*a%modd;b>>=1;}return res;}
ll sqrtll(ll a){assert(a >= 0); ll r = (ll)sqrtl((ld)a)-1; while(r < 0 || (r+1)*(r+1) <= a) r++; return r;}
ll cbrtll(ll a){assert(a >= 0); ll r = (ll)cbrtl((ld)a)-1; while(r < 0 || (r+1)*(r+1)*(r+1) <= a) r++; return r;}
ll modinv(ll a, ll b){assert(a); if(a == 1) return 1; if(b == 1) return 0; ll ret = (1ll-b*modinv(b%a, a))/a; ret %= b; if(ret < 0) ret += b; return ret;}
inline ll divceil(ll x, ll y) { if(x >= 0) {return(x / y + (ll)(x % y != 0)); } else { return -((-x) / y); } }
inline ll divfloor(ll x, ll y) { if(x >= 0) { return x/y; } else { return -((-x)/y + (ll)((-x) % y != 0)); } }
inline bool inLR(ll x, ll L, ll R){ return (L <= x && x < R); }
inline bool inRect(ll pos_x, ll pos_y, ll rect_H, ll rect_W, ll rect_h = 0, ll rect_w = 0){ return (rect_h <= pos_x && pos_x < rect_H && rect_w <= pos_y && pos_y < rect_W); }

template<class T> vector<T> &operator++(vector<T>& v){for(T& x : v) x++; return v;}
template<class T> vector<T> &operator--(vector<T>& v){for(T& x : v) x--; return v;}
template<class T> vector<T> operator++(vector<T>& v, signed){auto res = v; for(T& x : v) x++; return res;}
template<class T> vector<T> operator--(vector<T>& v, signed){auto res = v; for(T& x : v) x--; return res;}
template<class T> vector<T> operator+=(vector<T>& v, const vector<T>& w){if(v.size() < w.size()) v.resize(w.size()); for(int i = 0; i < (int)w.size(); i++) v[i] += w[i]; return v;}
template<class T> vector<T> operator-=(vector<T>& v, const vector<T>& w){if(v.size() < w.size()) v.resize(w.size()); for(int i = 0; i < (int)w.size(); i++) v[i] -= w[i]; return v;}
template<class T> vector<T> operator*=(vector<T>& v, const vector<T>& w){if(v.size() < w.size()) v.resize(w.size()); for(int i = 0; i < (int)w.size(); i++) v[i] *= w[i]; return v;}
template<class T> vector<T> operator/=(vector<T>& v, const vector<T>& w){if(v.size() < w.size()) v.resize(w.size()); for(int i = 0; i < (int)w.size(); i++) v[i] /= w[i]; return v;}
template<class T> vector<T> operator+(vector<T> v, const vector<T>& w){return (v += w);}
template<class T> vector<T> operator-(vector<T> v, const vector<T>& w){return (v -= w);}
template<class T> vector<T> operator*(vector<T> v, const vector<T>& w){return (v *= w);}
template<class T> vector<T> operator/(vector<T> v, const vector<T>& w){return (v /= w);}
template<class T> vector<T> operator*=(vector<T>& v, T w){for(T& x : v) x*=w; return v;}
template<class T> vector<T> operator/=(vector<T>& v, T w){for(T& x : v) x/=w; return v;}
template<class T> vector<T> operator*(vector<T> v, T x){return (v *= x);}
template<class T> vector<T> operator/(vector<T> v, T x){return (v /= x);}

template<class S, class T> pair<S,T> operator+=(pair<S,T>& p, const pair<S,T>& q){p.fi+=q.fi, p.se+=q.se; return p;}
template<class S, class T> pair<S,T> operator+(pair<S,T> p, const pair<S,T>& q){return (p += q);}
template<class S, class T> pair<S,T> operator-=(pair<S,T>& p, const pair<S,T>& q){p.fi-=q.fi, p.se-=q.se; return p;}
template<class S, class T> pair<S,T> operator-(pair<S,T> p, const pair<S,T>& q){return (p -= q);}

template<class T> size_t HashCombine(const size_t seed,const T &v){ return seed^(std::hash<T>()(v)+0x9e3779b9+(seed<<6)+(seed>>2)); }
template<class T,class S> struct std::hash<std::pair<T,S>>{ size_t operator()(const std::pair<T,S> &keyval) const noexcept { return HashCombine(std::hash<T>()(keyval.first), keyval.second); } };
template<class T> struct std::hash<std::vector<T>>{ size_t operator()(const std::vector<T> &keyval) const noexcept { size_t s=0; for (auto&& v: keyval) s=HashCombine(s,v); return s; } };
template<int N> struct HashTupleCore{ template<class Tuple> size_t operator()(const Tuple &keyval) const noexcept{ size_t s=HashTupleCore<N-1>()(keyval); return HashCombine(s,std::get<N-1>(keyval)); } };
template <> struct HashTupleCore<0>{ template<class Tuple> size_t operator()(const Tuple &keyval) const noexcept{ return 0; } };
template<class... Args> struct std::hash<std::tuple<Args...>>{ size_t operator()(const tuple<Args...> &keyval) const noexcept { return HashTupleCore<tuple_size<tuple<Args...>>::value>()(keyval); } };

template <class T>
class modint_factorials
{
private:
    vector<T> invs;
    vector<T> fact;
    vector<T> inv_fact;
    int max_calculated = -1;
    modint_factorials() = default;
    void calculate_until(int n)
    {
        assert(n >= 0);
        long long mod = T::mod();
        if (n < 1)
            n = 1;
        invs.resize(n + 1);
        fact.resize(n + 1);
        inv_fact.resize(n + 1);
        if (max_calculated == -1)
        {
            invs[0] = 0;
            invs[1] = 1;
            fact[0] = 1;
            fact[1] = 1;
            inv_fact[0] = 1;
            inv_fact[1] = 1;
            max_calculated = 1;
        }
        if (n <= max_calculated)
            return;
        for (int i = max_calculated + 1; i <= n; i++)
        {
            invs[i] = invs[mod % i] * -(mod / i);
            fact[i] = fact[i - 1] * i;
            inv_fact[i] = inv_fact[i - 1] * invs[i];
        }
        max_calculated = n;
    }

public:
    static modint_factorials &instance()
    {
        static modint_factorials inst;
        return inst;
    }

    static void precompute(int n)
    {
        assert(n >= 0);
        instance().calculate_until(n);
    }
    static T mint_inv(int x)
    {
        assert(x != 0);
        if (x < 0)
            return -mint_inv(-x);
        modint_factorials &inst = instance();
        if (x > inst.max_calculated)
            inst.calculate_until(x);
        return inst.invs[x];
    }
    static T mint_factorial(int x)
    {
        assert(x >= 0);
        modint_factorials &inst = instance();
        if (x > inst.max_calculated)
            inst.calculate_until(x);
        return inst.fact[x];
    }
    static T mint_inv_factorial(int x)
    {
        assert(x >= 0);
        modint_factorials &inst = instance();
        if (x > inst.max_calculated)
            inst.calculate_until(x);
        return inst.inv_fact[x];
    }
    static T nPk(int n, int k)
    {
        if (k < 0)
            return 0;
        if (n < 0)
            return ((k & 1) ? -nPk(-n + k - 1, k) : nPk(-n + k - 1, k));
        if (n >= 0 && k > n)
            return 0;
        modint_factorials &inst = instance();
        if (n > inst.max_calculated)
            inst.calculate_until(n);
        return inst.fact[n] * inst.inv_fact[n - k];
    }
    static T nCk(int n, int k)
    {
        if (k < 0)
            return 0;
        if (n < 0)
            return ((k & 1) ? -nCk(-n + k - 1, k) : nCk(-n + k - 1, k));
        if (n >= 0 && k > n)
            return 0;
        modint_factorials &inst = instance();
        if (n > inst.max_calculated)
            inst.calculate_until(n);
        return inst.fact[n] * inst.inv_fact[k] * inst.inv_fact[n - k];
        ;
    }
};
using mint_factorials = modint_factorials<mint>;

struct FPS : vector<mint>
{
    using vector<mint>::vector;
    using vm = vector<mint>;
    using vvm = vector<vector<mint>>;
    using pm = pair<mint, mint>;
    using vpm = vector<pair<mint, mint>>;
    using ll = long long;
    using pi = pair<ll, ll>;
    using vi = vector<ll>;
    using vvi = vector<vector<ll>>;
    FPS(const vm &v)
    {
        FPS ret;
        ret.resize(v.size());
        rep(i, v.size()) ret[i] = v[i];
        *this = ret;
    }
    FPS(const vi &v)
    {
        FPS ret;
        ret.resize(v.size());
        rep(i, v.size()) ret[i] = v[i];
        *this = ret;
    }
    FPS operator+=(const FPS &other)
    {
        if (other.size() > size())
            resize(other.size());
        rep(i, other.size()) at(i) += other[i];
        return *this;
    }
    FPS operator-=(const FPS &other)
    {
        if (other.size() > size())
            resize(other.size());
        rep(i, other.size()) at(i) -= other[i];
        return *this;
    }
    FPS operator+=(const mint &m)
    {
        if (empty())
            resize(1);
        at(0) += m;
        return *this;
    }
    FPS operator-=(const mint &m)
    {
        if (empty())
            resize(1);
        at(0) -= m;
        return *this;
    }
    FPS operator*=(const mint &m)
    {
        rep(i, size()) at(i) *= m;
        return *this;
    }
    FPS operator/=(const mint &m)
    {
        mint mi = m.inv();
        rep(i, size()) at(i) *= mi;
        return *this;
    }
    FPS operator+(const FPS &other) const { return FPS(*this) += other; }
    FPS operator-(const FPS &other) const { return FPS(*this) -= other; }
    FPS operator+(const mint &m) const { return FPS(*this) += m; }
    FPS operator-(const mint &m) const { return FPS(*this) -= m; }
    FPS operator*(const mint &m) const { return FPS(*this) *= m; }
    FPS operator/(const mint &m) const
    {
        mint mi = m.inv();
        return FPS(*this) *= mi;
    }
    FPS operator-() const
    {
        FPS ret(size());
        rep(i, size()) ret[i] = -at(i);
        return ret;
    }
    FPS operator*(const FPS &other) const
    {
        return FPS(convolution(*this, other));
    }
    FPS operator*=(const FPS &other)
    {
        *this = FPS(convolution(*this, other));
        return *this;
    }
    void shrink()
    {
        while (size() > 0 && back() == 0)
            pop_back();
    }
    void reversed()
    {
        reverse(begin(), end());
    }
    FPS rev() const
    {
        FPS ret(*this);
        reverse(ret.begin(), ret.end());
        return ret;
    }
    FPS pre(ll k) const
    {
        return FPS(begin(), begin() + min((ll)size(), k));
    }
    FPS dot(FPS g) const
    {
        FPS ret(*this);
        if (ret.size() < g.size())
            ret.resize(g.size());
        rep(i, g.size()) ret[i] *= g[i];
        return ret;
    }
    FPS inv(ll N = -1) const
    {
        if (N == -1)
            N = size();
        FPS g;
        g += at(0).inv();
        ll k = 1;
        while (k < N)
        {
            k *= 2;
            g = (-pre(k) * g + 2) * g;
            g.resize(k);
        }
        g.resize(N);
        return g;
    }
    FPS operator/(const FPS &other) const
    {
        FPS ret = (*this) * other.inv(size());
        ret.resize(size());
        return ret;
    }
    FPS operator/=(const FPS &other)
    {
        *this = (*this) / other;
        return *this;
    }
    FPS operator>>(ll k) const
    {
        if ((ll)size() < k)
            return {};
        FPS ret(*this);
        ret.erase(ret.begin(), ret.begin() + k);
        return ret;
    }
    FPS operator<<(ll k) const
    {
        FPS ret(*this);
        ret.insert(ret.begin(), k, mint(0));
        return ret;
    }
    FPS diff() const
    {
        FPS ret = (*this) >> 1;
        rep(i, ret.size()) ret[i] *= i + 1;
        return ret;
    }
    FPS integral() const
    {
        FPS ret = (*this) << 1;
        rep(i, ret.size() - 1) ret[i + 1] *= mint_factorials::mint_inv(i + 1);
        return ret;
    }
    FPS log(ll N = -1) const
    {
        FPS ret(*this);
        if (N > -1)
            ret.resize(N);
        return (ret.diff() / ret).integral();
    }
    FPS exp(ll N = -1) const
    {
        if (N == -1)
            N = size();
        FPS g;
        g += 1;
        ll k = 1;
        while (k < N)
        {
            k *= 2;
            g = (pre(k) - g.log(k) + 1) * g;
            g.resize(k);
        }
        g.resize(N);
        return g;
    }
    FPS pow(ll k, ll N = -1) const
    {
        if (N == -1)
            N = size();
        if (k == 0)
        {
            FPS ret(N);
            if (N > 0)
                ret += 1;
            return ret;
        }
        FPS ret(*(this));
        ll n = ret.size();
        ll c = 0;
        while (c < n && ret[c] == 0)
            c++;
        if (c == n || c >= (N + k - 1) / k)
            return FPS(N);
        ret = ret >> c;
        mint a = ret[0];
        ret /= a;
        return ((ret.log(N - c * k) * k).exp(N - c * k) << (c * k)) * a.pow(k);
    }
    static mint modsqrt(mint a)
    {
        static constexpr int MOD = mint::mod();
        if (MOD == 2)
            return a;
        static constexpr int M = __builtin_ctzll(MOD - 1);
        static constexpr long long Q = (MOD - 1) >> M;
        static constexpr long long Q2 = (Q + 1) >> 1;
        static constexpr long long R = (MOD - 1) / 2;
        static constexpr long long G = internal::pow_mod_constexpr(internal::primitive_root<MOD>, Q, MOD);
        if (a == 0)
            return 0;
        if (a.pow(R) == -1)
            return -1;
        int k = 0;
        mint b = a.pow(Q);
        for (int i = 0; i < M; i++)
        {
            if (b.pow(1ll << (M - i - 1)) == -1)
            {
                b *= mint(G).pow(1ll << i);
                k |= 1ll << i;
            }
        }
        return a.pow(Q2) * mint(G).pow(k >> 1);
    }
    FPS _sqrt(ll N = -1) const
    {
        if (N == -1)
            N = size();
        FPS g;
        g += 1;
        ll k = 1;
        while (k < N)
        {
            k *= 2;
            g = (g + pre(k) * g.inv(k)) / 2;
            g.resize(k);
        }
        g.resize(N);
        return g;
    }
    FPS sqrt(ll N = -1) const
    {
        if (N == -1)
            N = size();
        FPS ret(*(this));
        ll n = ret.size();
        ll c = 0;
        while (c < n && ret[c] == 0)
            c++;
        if (c == n)
            return FPS(N);
        if (c & 1)
            return {};
        ret = ret >> c;
        mint a = ret[0];
        mint b = modsqrt(a);
        if (b == -1)
            return {};
        ret /= a;
        return (ret._sqrt(N - c / 2) << (c / 2)) * b;
    }
    pair<FPS, FPS> div(FPS g) const
    {
        FPS f(*this);
        f.shrink();
        g.shrink();
        ll n = f.size();
        ll m = g.size();
        if (n < m)
            return {{}, f};
        FPS q = f.rev();
        g.reversed();
        q /= g;
        q.resize(n - m + 1);
        q.reversed();
        g.reversed();
        FPS r = f - g * q;
        r.shrink();
        return {q, r};
    }
    mint eval(mint x) const
    {
        mint ans = 0;
        rrep(i, size())
        {
            ans *= x;
            ans += at(i);
        }
        return ans;
    }
    vm mult_eval(vm p) const
    {
        ll n = p.size();
        if (n == 0)
            return {};
        ll N = 1ll << (64 - __builtin_clzll(n - 1));
        vector<FPS> g(2 * N);
        vector<FPS> r(N);
        vm ans(n);
        rep(i, n) g[i + N] = {-p[i], 1};
        rep(i, n, N) g[i + N] = {1};
        rrep(i, 1, N) g[i] = g[2 * i] * g[2 * i + 1];
        r[0] = (*this);
        rep(i, 1, N) r[i] = r[i / 2].div(g[i]).second;
        rep(i, n) ans[i] = r[(i + N) / 2].eval(p[i]);
        return ans;
    }
    vm to_newton(vm p) const
    {
        assert(p.size() == size());
        ll n = size();
        if (n == 0)
            return {};
        ll N = 1ll << (64 - __builtin_clzll(n - 1));
        vector<FPS> g(2 * N);
        vector<FPS> r(2 * N);
        vm ans(n);
        rep(i, n) g[i + N] = {-p[i], 1};
        rep(i, n, N) g[i + N] = {1};
        rrep(i, 1, N) g[i] = g[2 * i] * g[2 * i + 1];
        r[1] = (*this);
        rep(i, 1, N)
        {
            auto [p, q] = r[i].div(g[2 * i]);
            r[2 * i] = q, r[2 * i + 1] = p;
        }
        rep(i, n) ans[i] = r[i + N].empty() ? 0 : r[i + N][0];
        return ans;
    }
    static FPS prod(vector<FPS> F)
    {
        ll n = F.size();
        if (n == 0)
            return {1};
        priority_queue<pi, vector<pi>, greater<pi>> q;
        rep(i, n) q.push({F[i].size(), i});
        while (q.size() > 1)
        {
            ll i = q.top().second;
            q.pop();
            ll j = q.top().second;
            q.pop();
            F[i] *= F[j];
            q.push({F[i].size(), i});
        }
        return F[q.top().second];
    }
    static FPS quotient_sum(vector<pair<FPS, FPS>> QR, ll d = -1)
    {
        FPS ans;
        ll n = QR.size();
        rep(i, n)
        {
            if (QR[i].first.size() >= QR[i].second.size())
            {
                pair<FPS, FPS> p = QR[i].first.div(QR[i].second);
                ans += p.first;
                QR[i].first = p.second;
            }
        }
        ll k = 1;
        while (k < n)
        {
            for (ll i = 0; i + k < n; i += (k << 1))
            {
                QR[i] = {
                    QR[i].second * QR[i + k].first + QR[i].first * QR[i + k].second,
                    QR[i].second * QR[i + k].second};
            }
            k = k << 1;
        }
        if (d == -1)
            d = max(ans.size(), QR[0].second.size());
        ans += QR[0].first * QR[0].second.inv(d);
        ans.resize(d);
        return ans;
    }
    vm geo_eval(mint a, mint r, ll m)
    {
        if (m == 0)
            return {};
        ll n = size();
        if (n == 0)
            return {};
        if (r == 0)
        {
            vm ret(m, at(0));
            ret[0] = eval(a);
            return ret;
        }
        FPS x(n + m, 1), y(n, 1);
        mint e = 1;
        mint ri = r.inv();
        rep(i, n + m - 1)
        {
            x[i + 1] = e * x[i];
            e *= r;
        }
        e = 1;
        rrep(i, n - 1)
        {
            y[i] = a * e * y[i + 1];
            e *= ri;
        }
        rep(i, n) y[i] *= at(n - i - 1);
        FPS z = x * y;
        vm ret(m);
        e = 1;
        mint f = 1;
        rep(i, m)
        {
            ret[i] = f * z[n + i - 1];
            f *= e;
            e *= ri;
        }
        return ret;
    }
    static FPS interpolation(const vm &x, const vm &y)
    {
        ll n = x.size();
        if (n == 0)
            return {};
        vector<FPS> g0(n);
        rep(i, n) g0[i] = {-x[i], 1};
        FPS G = prod(g0);
        vm g = G.diff().mult_eval(x);
        vector<pair<FPS, FPS>> qr(n);
        ll flag = -1;
        rep(i, n) qr[i].first = {y[i]};
        rep(i, n)
        {
            if (x[i] == 0)
            {
                qr[i] = {{0}, {1}};
                flag = i;
            }
            else
                qr[i].second = {-g[i] * x[i], g[i]};
        }
        FPS ret = quotient_sum(qr, n) * G;
        if (flag >= 0)
            ret += (G >> 1) * (y[flag] / g[flag]);
        ret.resize(n);
        return ret;
    }
    static FPS geo_interpolation(const vm &y, mint a, mint r)
    {
        ll n = y.size();
        if (!n)
            return {};
        if (n == 1)
            return {y[0]};
        FPS g(n + 1);
        g[n] = 1;
        mint rn = r.pow(n);
        mint ri = r.inv();
        mint ai = a.inv();
        mint e = 1;
        if (rn == 1)
            g[0] = -a.pow(n);
        else
        {
            rrep(i, n)
            {
                g[i] = g[i + 1] * a * (e - rn) / (e * r - 1);
                e *= r;
            }
        }
        vm s = g.diff().geo_eval(a, r, n);
        g.pop_back();
        FPS c(n);
        rep(i, n) c[i] = y[i] / s[i];
        FPS f(c.geo_eval(ri, ri, n + 1));
        e = -ai;
        rep(i, n + 1)
        {
            f[i] *= e;
            e *= ai;
        }
        return (g * f).pre(n);
    }
    FPS Taylor_shift(mint a) const
    {
        if (a == 0)
            return *this;
        FPS ret(*this);
        ll n = size();
        rep(i, n) ret[i] *= mint_factorials::mint_factorial(i);
        FPS g(n, 1);
        rep(i, n - 1) g[i + 1] = g[i] * a;
        rep(i, n) g[i] *= mint_factorials::mint_inv_factorial(i);
        ret = ret.rev() * g;
        ret.resize(n);
        ret.reversed();
        rep(i, n) ret[i] *= mint_factorials::mint_inv_factorial(i);
        return ret;
    }
    // return (cx+d)^n f((ax+b)/(cx+d))
    FPS Mobius_Transform(mint a, mint b, mint c, mint d) const
    {
        mint tmp;
        if (empty())
            return {};
        int n = size() - 1;
        if (c == 0)
        {
            if (d == 0)
            {
                FPS res(n + 1);
                tmp = back();
                rep(i, n + 1)
                {
                    res[i] = mint_factorials::nCk(n, i) * tmp;
                    tmp *= a;
                }
                tmp = 1;
                rrep(i, n + 1)
                {
                    res[i] *= tmp;
                    tmp *= b;
                }
                return res;
            }
            FPS res(*this);
            tmp = 1;
            rrep(i, n + 1)
            {
                res[i] *= tmp;
                tmp *= d;
            }
            rep(i, n + 1) res[i] *= mint_factorials::mint_factorial(i);
            FPS g(n + 1, 1);
            rep(i, n) g[i + 1] = g[i] * b * mint_factorials::mint_inv(i + 1);
            reverse(res.begin(), res.end());
            res = convolution(res, g);
            res.resize(n + 1);
            reverse(res.begin(), res.end());
            rep(i, n + 1) res[i] *= mint_factorials::mint_inv_factorial(i);
            tmp = 1;
            rep(i, n + 1)
            {
                res[i] *= tmp;
                tmp *= a;
            }
            return res;
        }
        a /= c;
        FPS res(*this);
        rep(i, n + 1) res[i] *= mint_factorials::mint_factorial(i);
        FPS g(n + 1, 1);
        rep(i, n) g[i + 1] = g[i] * a * mint_factorials::mint_inv(i + 1);
        reverse(res.begin(), res.end());
        res = convolution(res, g);
        res.resize(n + 1);
        b -= a * d;
        tmp = 1;
        rrep(i, n + 1)
        {
            res[i] *= tmp * mint_factorials::mint_factorial(i) * mint_factorials::mint_inv_factorial(n - i);
            tmp *= b;
        }
        rep(i, n) g[i + 1] = g[i] * d * mint_factorials::mint_inv(i + 1);
        reverse(res.begin(), res.end());
        res = convolution(res, g);
        res.resize(n + 1);
        reverse(res.begin(), res.end());
        rep(i, n + 1) res[i] *= mint_factorials::mint_inv_factorial(i);
        tmp = 1;
        rep(i, n + 1)
        {
            res[i] *= tmp;
            tmp *= c;
        }
        return res;
    }
    // FPS composition(FPS G, ll deg = -1) const {
    //   if(deg == -1) deg = size();
    //   ll n = size();
    //   if((ll)G.size() > deg) G.resize(deg);
    //   if(n == 0) return FPS(deg);
    //   ll k = max((ll)sqrtl(n), 1ll);
    //   ll l = (n+k-1)/k;
    //   vector<FPS> Pi(l);
    //   FPS Qb = {1};
    //   rep(i,k){
    //     rep(j,l){
    //       if(i + j*k < n){
    //         Pi[j] += Qb * at(i + j*k);
    //       }
    //     }
    //     Qb *= G;
    //     if((ll)Qb.size() > deg) Qb.resize(deg);
    //   }
    //   FPS ret;
    //   FPS Qg = {1};
    //   rep(i,l){
    //     ret += (Pi[i] * Qg).pre(deg);
    //     Qg *= Qb;
    //     if((ll)Qg.size() > deg) Qg.resize(deg);
    //   }
    //   return ret;
    // }
    static vm shift_sampling(vm f, mint c, ll m = -1)
    {
        ll n = f.size() - 1;
        if (m == -1)
            m = n;
        if (m == 1)
        {
            if (c.val() <= n)
                return {f[c.val()]};
            mint t = 1;
            mint s1 = 1;
            mint s2 = 1;
            rep(i, n + 1)
            {
                f[i] *= s1 / t;
                f[n - i] *= s2 / t;
                t *= i + 1;
                s1 *= c - i;
                s2 *= c - n + i;
                if ((i + n) & 1)
                    f[i] *= -1;
            }
            mint ans = 0;
            rep(i, n + 1) ans += f[i];
            return {ans};
        }
        n++;
        if (f.size() == 0)
            return vm(0, m);
        FPS F(n);
        rep(i, n) F[i] = f[i] * mint_factorials::mint_inv_factorial(i);
        FPS G(n);
        rep(i, n) G[i] = mint_factorials::mint_inv_factorial(i) * (i & 1 ? -1 : 1);
        F *= G;
        F.resize(n);
        rep(i, n) F[i] *= mint_factorials::mint_factorial(i);
        FPS H(n, 1);
        rep(i, n - 1) H[i + 1] = H[i] * (c - i);
        rep(i, n) H[i] *= mint_factorials::mint_inv_factorial(i);
        F = ((F * H.rev()) >> (n - 1));
        rep(i, n) F[i] *= mint_factorials::mint_inv_factorial(i);
        FPS I(m);
        rep(i, m) I[i] = mint_factorials::mint_inv_factorial(i);
        F = (F * I).pre(m);
        rep(i, m) F[i] *= mint_factorials::mint_factorial(i);
        return F;
    }
    FPS times_sparse(const vector<pair<ll, mint>> &x, ll deg = -1) const
    {
        if (deg == -1)
            deg = size();
        FPS ret(deg);
        for (auto [i, a] : x)
        {
            ret += ((*this) << i).pre(deg) * a;
        }
        return ret;
    }
    static FPS inv_sparse(const vector<pair<ll, mint>> &x, ll deg)
    {
        if (deg == 0)
            return {};
        FPS ret(deg);
        mint a = x[0].second.inv();
        ret[0] = a;
        rep(i, 1, deg)
        {
            rep(j, 1, x.size())
            {
                if (x[j].first > i)
                    break;
                ret[i] -= ret[i - x[j].first] * x[j].second;
            }
            ret[i] *= a;
        }
        return ret;
    }
    static FPS log_sparse(const vector<pair<ll, mint>> &x, ll deg)
    {
        if (deg == 0)
            return {};
        FPS ret = inv_sparse(x, deg - 1);
        vector<pair<ll, mint>> y = {x.begin() + 1, x.end()};
        rep(i, y.size())
        {
            y[i].second *= y[i].first;
            y[i].first--;
        }
        return ret.times_sparse(y).integral();
    }
    static FPS exp_sparse(const vector<pair<ll, mint>> &x, ll deg)
    {
        if (deg == 0)
            return {};
        FPS ret(deg);
        ret[0] = 1;
        rep(i, 1, deg)
        {
            rep(j, x.size())
            {
                if (x[j].first > i)
                    break;
                ret[i] += ret[i - x[j].first] * x[j].second * x[j].first;
            }
            ret[i] *= mint_factorials::mint_inv(i);
        }
        return ret;
    }
    static FPS _pow_sparse(const vector<pair<ll, mint>> &x, mint m, ll deg)
    {
        if (deg == 0)
            return {};
        FPS ret(deg);
        ret[0] = 1;
        rep(i, 1, deg)
        {
            rep(j, 1, x.size())
            {
                if (x[j].first > i)
                    break;
                ret[i] += ret[i - x[j].first] * x[j].second * ((m + 1) * x[j].first - i);
            }
            ret[i] *= mint_factorials::mint_inv(i);
        }
        return ret;
    }
    static FPS pow_sparse(vector<pair<ll, mint>> x, ll m, ll deg)
    {
        if (deg == 0)
            return {};
        if (m == 0)
        {
            FPS ret(deg);
            return ret + 1;
        }
        if (x.empty())
            return FPS(deg);
        ll c = x[0].first;
        if (c >= (deg + m - 1) / m)
            return FPS(deg);
        mint a = x[0].second;
        mint ai = a.inv();
        rep(i, x.size())
        {
            x[i].first -= c;
            x[i].second *= ai;
        }
        return ((_pow_sparse(x, m, deg - c * m) * a.pow(m)) << (c * m));
    }
    static FPS _sqrt_sparse(vector<pair<ll, mint>> x, ll deg)
    {
        return _pow_sparse(x, mint_factorials::mint_inv(2), deg);
    }
    static FPS sqrt_sparse(vector<pair<ll, mint>> x, ll deg)
    {
        if (deg == 0)
            return {};
        if (x.empty())
            return FPS(deg);
        ll c = x[0].first;
        if (c & 1)
            return {};
        mint a = x[0].second;
        mint b = modsqrt(a);
        if (b == -1)
            return {};
        rep(i, x.size())
        {
            x[i].first -= c;
            x[i].second /= a;
        }
        return ((_sqrt_sparse(x, deg - c / 2) * b) << (c / 2));
    }
    mint prefix_product(ll k) const
    {
        ll deg = size() - 1;
        if (k <= deg + 1)
        {
            mint ret = 1;
            rep(i, k) ret *= eval(i);
            return ret;
        }
        ll b = 0;
        while ((((deg << (b + 1)) + 1) << (b + 1)) < k)
            b++;
        // mint B = (1ll << b);
        vm G(deg + 1);
        rep(i, deg + 1)
        {
            G[i] = eval(i << b);
        }
        mint twoi = mint(2).inv();
        mint t = 1;
        rep(i, b)
        {
            t *= twoi;
            vm G1 = shift_sampling(G, t, (deg << i) + 1);
            vm G2 = shift_sampling(G, (deg << i) + 1, deg << i);
            vm G3 = shift_sampling(G, (deg << i) + 1 + t, deg << i);
            rep(j, G.size()) G[j] *= G1[j];
            rep(j, G2.size()) G.push_back(G2[j] * G3[j]);
        }
        mint ret = 1;
        G = shift_sampling(G, 0, k >> b);
        for (mint a : G)
            ret *= a;
        rep(i, k & ~((1ll << b) - 1), k) ret *= eval(i);
        return ret;
    }
    static mint Bostan_Mori(FPS F, FPS G, ll k)
    {
        while (k)
        {
            if (F.empty())
                return 0;
            FPS G2(G.size());
            rep(i, G.size()) G2[i] = (i & 1 ? -G[i] : G[i]);
            FPS F2 = F * G2;
            G2 *= G;
            rep(i, G.size()) G[i] = G2[i * 2];
            if (k & 1)
            {
                F.resize(F2.size() / 2);
                rep(i, F.size()) F[i] = F2[i * 2 + 1];
            }
            else
            {
                F.resize((F2.size() + 1) / 2);
                rep(i, F.size()) F[i] = F2[i * 2];
            }
            k >>= 1;
        }
        return F[0] / G[0];
    }
    // returns [x^{N-1}]] GF^i for i=0,...,M-1
    static FPS PowerProjection(FPS F, FPS G, ll N, ll M)
    {
        static constexpr int g = internal::primitive_root<mint::mod()>;
        static int cnt2 = __builtin_ctz(mint::mod() - 1);
        static constexpr int inv2 = (mint::mod() + 1) >> 1;
        static mint e2 = mint(g).pow((mint::mod() - 1) >> cnt2), ie2 = e2.inv();
        static bool first = true;
        static vm es(cnt2 + 1), ies(cnt2 + 1), sum_ie(cnt2 + 1);
        if (first)
        {
            first = false;
            es[cnt2] = e2, ies[cnt2] = ie2;
            rrep(i, cnt2) es[i] = es[i + 1] * es[i + 1], ies[i] = ies[i + 1] * ies[i + 1];
            mint e = 1;
            rep(i, cnt2 + 1)
            {
                sum_ie[i] = ies[i] * e;
                e *= es[i];
            }
        }

        ll n = 64 - __builtin_clzll(N - 1);
        G = G << ((1ll << n) - N);
        N = 1ll << n;
        F.resize(N);
        G.resize(N);
        ll n2 = 0, N2 = 1;
        mint invN = mint(N).inv(), invN2 = 1;
        vector<FPS> P = {G}, Q = {-F};
        while (N > 1)
        {
            vector<FPS> NP(N2 << 1, FPS(N << 1, 0)), NQ(N2 << 1, FPS(N << 1, 0));
            rep(i, N2) rep(j, N) NP[i][j] = P[i][j], NQ[i][j] = Q[i][j];
            rep(j, N)
            {
                vm p(N2), q(N2);
                rep(i, N2) p[i] = P[i][j], q[i] = Q[i][j];
                internal::butterfly_inv(p), internal::butterfly_inv(q);
                mint e = 1;
                rep(i, N2)
                {
                    p[i] *= e;
                    q[i] *= e;
                    e *= es[n2 + 1];
                }
                internal::butterfly(p), internal::butterfly(q);
                rep(i, N2) NP[i + N2][j] = p[i] * invN2, NQ[i + N2][j] = q[i] * invN2;
            }
            P = vector<FPS>(N2 << 1, FPS(N)), Q = vector<FPS>(N2 << 1, FPS(N));
            rep(i, N2 << 1)
            {
                NQ[i][0] += (i & N2 ? -1 : 1);
                internal::butterfly(NP[i]), internal::butterfly(NQ[i]);
                mint e = 1;
                rep(j, N)
                {
                    Q[i][j] = (NQ[i][2 * j] * NQ[i][2 * j + 1]) * invN;
                    P[i][j] = (NP[i][2 * j] * NQ[i][2 * j + 1] - NP[i][2 * j + 1] * NQ[i][2 * j]) * invN * inv2 * e;
                    e *= -sum_ie[__builtin_ctz(~(unsigned int)(j)) + 2];
                }
                internal::butterfly_inv(P[i]), internal::butterfly_inv(Q[i]);
                P[i].resize(N >> 1);
                Q[i].resize(N >> 1);
                Q[i][0]--;
            }
            N >>= 1;
            n--;
            invN *= 2;
            N2 <<= 1;
            n2++;
            invN2 *= inv2;
        }
        FPS p(N2), q(N2);
        rep(i, N2) p[i] = P[i][0] * invN2, q[i] = Q[i][0] * invN2;
        internal::butterfly_inv(p);
        internal::butterfly_inv(q);
        q.push_back(1);
        reverse(p.begin(), p.end());
        reverse(q.begin(), q.end());
        p.resize(M);
        q.resize(M);
        return p / q;
    }

    static FPS compositional_inverse(FPS F, ll m = -1)
    {
        if (m == -1)
            m = F.size();
        assert(F.size() > 1);
        assert(F[0].val() == 0);
        mint c = F[1].inv();
        F *= c;
        FPS G = PowerProjection(F, {1}, m, m);
        rep(i, 1, m) G[i] *= mint_factorials::mint_inv(i) * (m - 1);
        reverse(G.begin(), G.end());
        G.pop_back();
        G = G.pow((-mint_factorials::mint_inv(m - 1)).val()) << 1;
        mint e = c;
        rep(i, 1, m)
        {
            G[i] *= e;
            e *= c;
        }
        return G;
    }

    // return F(G(X))
    static FPS composition(FPS F, FPS G, ll m = -1)
    {
        static constexpr int g = internal::primitive_root<mint::mod()>;
        static int cnt2 = __builtin_ctz(mint::mod() - 1);
        static constexpr int inv2 = (mint::mod() + 1) >> 1;
        static mint e2 = mint(g).pow((mint::mod() - 1) >> cnt2), ie2 = e2.inv();
        static bool first = true;
        static vm es(cnt2 + 1), ies(cnt2 + 1), sum_ie(cnt2 + 1);
        if (first)
        {
            first = false;
            es[cnt2] = e2, ies[cnt2] = ie2;
            rrep(i, cnt2) es[i] = es[i + 1] * es[i + 1], ies[i] = ies[i + 1] * ies[i + 1];
            mint e = 1;
            rep(i, cnt2 + 1)
            {
                sum_ie[i] = ies[i] * e;
                e *= es[i];
            }
        }

        if (m == -1)
            m = max(F.size(), G.size());
        if (F.empty())
            return FPS(1, m);
        if (G.empty())
        {
            FPS ret(1, F[0]);
            ret.resize(m);
            return ret;
        }
        if (m == 1)
            return {F[0]};
        ll n = 64 - __builtin_clzll(m - 1);
        ll N = 1ll << n;
        F.resize(N);
        G.resize(N);
        ll n2 = 0, N2 = 1;
        mint invN = mint(N).inv(), invN2 = 1;
        vector<FPS> Q = {-G};
        vector<vector<FPS>> NQ(n);
        while (N > 1)
        {
            NQ[n2] = vector<FPS>(N2 << 1, FPS(N << 1, 0));
            rep(i, N2) rep(j, N) NQ[n2][i][j] = Q[i][j];
            rep(j, N)
            {
                vm q(N2);
                rep(i, N2) q[i] = Q[i][j];
                internal::butterfly_inv(q);
                mint e = 1;
                rep(i, N2)
                {
                    q[i] *= e;
                    e *= es[n2 + 1];
                }
                internal::butterfly(q);
                rep(i, N2) NQ[n2][i + N2][j] = q[i] * invN2;
            }
            Q = vector<FPS>(N2 << 1, FPS(N));
            rep(i, N2 << 1)
            {
                NQ[n2][i][0] += (i & N2 ? -1 : 1);
                internal::butterfly(NQ[n2][i]);
                rep(j, N) Q[i][j] = (NQ[n2][i][2 * j] * NQ[n2][i][2 * j + 1]) * invN;
                internal::butterfly_inv(Q[i]);
                Q[i].resize(N >> 1);
                Q[i][0]--;
            }
            N >>= 1;
            n--;
            invN *= 2;
            N2 <<= 1;
            n2++;
            invN2 *= inv2;
        }
        FPS q(N2);
        rep(i, N2) q[i] = Q[i][0] * invN2;
        internal::butterfly_inv(q);
        q.push_back(1);
        reverse(q.begin(), q.end());
        q = q.inv(N2);
        reverse(q.begin(), q.end());
        F *= q;
        F[0] = F.back();
        rep(i, 1, N2) F[i] = F[i + N2 - 2];
        F.resize(N2);
        internal::butterfly(F);

        vector<FPS> P(N2, FPS(1));
        rep(i, N2) P[i][0] = F[i] * invN2;

        while (N2 > 1)
        {
            N <<= 1;
            n++;
            invN *= inv2;
            N2 >>= 1;
            n2--;
            invN2 *= 2;
            vector<FPS> NP(N2 << 1, FPS(N << 1, 0));
            rep(i, N2 << 1)
            {
                P[i].resize(N);
                reverse(P[i].begin() + 1, P[i].end());
                internal::butterfly(P[i]);
                mint e = 1;
                rep(j, N)
                {
                    NP[i][2 * j] = P[i][j] * NQ[n2][i][2 * j + 1] * invN * inv2 * e;
                    NP[i][2 * j + 1] = -P[i][j] * NQ[n2][i][2 * j] * invN * inv2 * e;
                    e *= -sum_ie[__builtin_ctz(~(unsigned int)(j)) + 2];
                }
                internal::butterfly_inv(NP[i]);
                reverse(NP[i].begin() + 1, NP[i].end());
            }
            P = vector<FPS>(N2, FPS(N, 0));
            rep(i, N2) rep(j, N) P[i][j] = NP[i][j];
            rep(j, N)
            {
                vector<mint> p(N2);
                rep(i, N2) p[i] = NP[i + N2][j] * invN2;
                internal::butterfly_inv(p);
                mint e = es[n2 + 1];
                rep(i, 1, N2)
                {
                    p[N2 - i] *= e;
                    e *= es[n2 + 1];
                }
                internal::butterfly(p);
                rep(i, N2) P[i][j] += p[i];
            }
        }
        reverse(P[0].begin(), P[0].end());
        return P[0].pre(m);
    }
};

struct FPS_Mat
{
    FPS a, b, c, d;
    FPS_Mat() = default;
    FPS_Mat(const FPS &a0, const FPS &b0, const FPS &c0, const FPS &d0)
        : a(a0), b(b0), c(c0), d(d0) {};

    FPS_Mat &operator*=(const FPS_Mat &r)
    {
        FPS A = a * r.a + b * r.c;
        FPS B = a * r.b + b * r.d;
        FPS C = c * r.a + d * r.c;
        FPS D = c * r.b + d * r.d;
        A.shrink();
        B.shrink();
        C.shrink();
        D.shrink();
        swap(A, a);
        swap(B, b);
        swap(C, c);
        swap(D, d);
        return *this;
    }
    static FPS_Mat I() { return {{1}, {}, {}, {1}}; }
    FPS_Mat operator*(const FPS_Mat &r) const
    {
        return FPS_Mat(*this) *= r;
    }

    pair<FPS, FPS> app(const pair<FPS, FPS> &p) const
    {
        FPS q1 = a * p.first + b * p.second;
        FPS q2 = c * p.first + d * p.second;
        q1.shrink();
        q2.shrink();
        return {q1, q2};
    }
};

void Naive_GCD(FPS_Mat &M, pair<FPS, FPS> &p, mint &res, int pre)
{
    pair<FPS, FPS> qr = p.first.div(p.second);
    FPS C = M.a - M.c * qr.first;
    FPS D = M.b - M.d * qr.first;
    res *= p.second.back().pow(p.first.size() - qr.second.size());
    res *= ((~(p.first.size() ^ pre) & 1) && (~(p.second.size() ^ pre) & 1) ? -1 : 1);
    C.shrink();
    D.shrink();
    swap(C, M.c);
    swap(D, M.d);
    swap(C, M.a);
    swap(D, M.b);
    p = {p.second, qr.second};
}

FPS_Mat Half_GCD(pair<FPS, FPS> p, mint &res, int pre = 0)
{
    int n = p.first.size();
    int m = p.second.size();
    int k = (n + 1) / 2;
    if (m <= k)
        return FPS_Mat::I();
    auto R1 = Half_GCD({p.first >> k, p.second >> k}, res, pre + k);
    p = R1.app(p);
    if ((int)p.second.size() < k)
        res *= p.first.back().pow(k - p.second.size());
    if ((int)p.second.size() <= k)
        return R1;
    Naive_GCD(R1, p, res, pre);
    if ((int)p.second.size() <= k)
        return R1;
    int l = p.first.size() - 1;
    int j = 2 * k - l;
    p.first = p.first >> j;
    p.second = p.second >> j;
    return Half_GCD(p, res, pre + j) * R1;
}

pair<FPS_Mat, mint> GCD_Mat(const FPS &f, const FPS &g)
{
    pair<FPS, FPS> p{f, g};
    mint res = 1;
    p.first.shrink();
    p.second.shrink();
    int n = p.first.size();
    int m = p.second.size();
    if (n < m)
    {
        auto [ret, res0] = GCD_Mat(p.second, p.first);
        if ((~n & 1) && (~m & 1))
            res0 *= -1;
        swap(ret.a, ret.b);
        swap(ret.c, ret.d);
        return {ret, res0 * res};
    }
    FPS_Mat ret = FPS_Mat::I();
    while (true)
    {
        auto m1 = Half_GCD(p, res);
        p = m1.app(p);
        if (p.second.empty())
            return {m1 * ret, res};
        Naive_GCD(m1, p, res, 0);
        if (p.second.empty())
            return {m1 * ret, res};
        ret = m1 * ret;
    }
}

FPS PolyGCD(const FPS &f, const FPS &g)
{
    pair<FPS, FPS> p{f, g};
    FPS_Mat m = GCD_Mat(f, g).first;
    p = m.app(p);
    if (!p.first.empty())
        p.first *= p.first.back().inv();
    return p.first;
}
pair<bool, FPS> PolyInv(const FPS &f, const FPS &g)
{
    pair<FPS, FPS> p{f, g};
    FPS_Mat m = GCD_Mat(f, g).first;
    FPS gcd_ = m.app(p).first;
    if ((int)gcd_.size() != 1)
        return {false, FPS()};
    return {true, m.a * gcd_.back().inv()};
}
mint Resolutant(const FPS &f, const FPS &g)
{
    pair<FPS, FPS> p{f, g};
    auto [m, res] = GCD_Mat(f, g);
    FPS gcd_ = m.app(p).first;
    if ((int)gcd_.size() != 1)
        return 0;
    return {res * gcd_.back().inv()};
}

vector<mint> FindRoot(FPS F)
{
    static random_device rnd;
    static mt19937 mt(rnd());
    static uniform_int_distribution<> randp(0, mint::mod() - 1);
    static constexpr long long q = (mint::mod() - 1) >> 1;
    F.shrink();
    int n = F.size();
    if (n <= 1)
        return {};
    if (n == 2)
        return {-F[0] / F[1]};
    FPS Frevinv = F.rev().inv();
    static function<void(FPS &, FPS &, FPS &)> modf = [&](FPS &G, FPS &f, FPS &finv)
    {
        if (G.size() >= f.size())
        {
            FPS Q = (G.rev() * finv).pre(G.size() - f.size() + 1).rev();
            G -= f * Q;
            G.shrink();
        }
    };
    FPS G = {1};
    FPS G2 = {0, 1};
    long long k = mint::mod();
    while (k)
    {
        if (k & 1)
        {
            G *= G2;
            modf(G, F, Frevinv);
        }
        G2 *= G2;
        modf(G2, F, Frevinv);
        k = k >> 1;
    }
    G -= {0, 1};
    F = PolyGCD(F, G);
    n = F.size();
    if (n <= 1)
        return {};
    if (n == 2)
        return {-F[0] / F[1]};
    Frevinv = F.rev().inv();
    vector<mint> ans = {};
    vector<FPS> FS = {F};
    while (!FS.empty())
    {
        mint s = randp(mt);
        vector<FPS> NFS;
        for (FPS &f : FS)
        {
            if (f.eval(s) == 0)
                ans.push_back(s);
            FPS frevinv = f.rev().inv();
            FPS g = {1};
            FPS g2 = {-s, 1};
            long long k = q;
            while (k)
            {
                if (k & 1)
                {
                    g *= g2;
                    modf(g, f, frevinv);
                }
                g2 *= g2;
                modf(g2, f, frevinv);
                k = k >> 1;
            }
            g -= 1;
            FPS f1 = PolyGCD(f, g);
            g += 2;
            FPS f2 = PolyGCD(f, g);
            if (f1.size() == 2)
                ans.push_back(-f1[0]);
            else if (f1.size() > 2)
                NFS.push_back(f1);
            if (f2.size() == 2)
                ans.push_back(-f2[0]);
            else if (f2.size() > 2)
                NFS.push_back(f2);
        }
        FS = NFS;
    }
    return ans;
}

int main()
{
    std::cin.tie(nullptr), std::ios_base::sync_with_stdio(false);
    readll(N, M, K, L);
    if(N == K || L == M)
    {
        dame(0);
    }
    mint ans = 0;
    // FPS f(M + 1, 1);
    {
        for(ll i = 0; i*(M + 1) <= M*K && i <= N; i++)
        {
            ans += ((i&1) == 0 ? 1 : (-1))*mint_factorials::nCk(N, i)*mint_factorials::nCk(M*K-(i*(M+1)) + N - 1, N - 1);
        }
    }
    // debug(ans);
    {
        // FPS g(L, 1);
        // ans -= (g * f.pow(N-1, M*K + 1))[M*K];
        REP(k, 0, L-1)
        {
            for(ll i = 0; i*(M + 1) <= M*K && i <= N - 1; i++) ans -= ((i&1) == 0 ? 1 : (-1))*mint_factorials::nCk(N-1, i)*mint_factorials::nCk(M*K-k -(i*(M+1)) + N - 2, N - 2);
        }
    }
    // debug(ans);
    REP(k, L, M)
    {
        mint tmp = 0;
        for(ll i = 0; i*(k+1) <= M*K - k && i <= N - 1; i++)
        {
            tmp += ((i&1) == 0 ? 1 : (-1))*mint_factorials::nCk(N-1, i)*mint_factorials::nCk(M*K-k-(i*(k+1)) + N - 2, N - 2);
        }
        // debug(tmp);
        ans -= tmp;
    }
    out(ans);
}
0