#ifndef ONLINE_JUDGE #define _GLIBCXX_DEBUG #endif #include "atcoder/all" #include #include #include /* Boostが使用したかったら WSLの方で開いて #include #include #include #include // 任意長整数型 using Bint = boost::multiprecision::cpp_int; // 仮数部が10進数で1024桁の浮動小数点数型(TLEしたら小さくする) using BReal = boost::multiprecision::number>; using Rat = boost::rational; */ #include #include using namespace std; using namespace __gnu_pbds; // 型エイリアスの設定 template using ordered_set = tree, rb_tree_tag, tree_order_statistics_node_update>; using namespace atcoder; template inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; } template inline bool chmin(T &a, T b) { return ((a>b) ? (a = b, true) : (false));} #define rep(i,n) for(int i=0;i<(int)(n);i++) #define drep(i,n) for(int i=n-1;i>=0;i--) #define REP(i,s,n) for(int i=s;i<(int)n;i++) #define DREP(i,s,n) for(int i=n-1;i>=s;i--) const long long inf = 1LL<<60; const int infi = 1e9+1; typedef long long ll; typedef long double ld; typedef __int128_t l3; //cmpArg := 偏角ソート, atan2l(y, x); atan2l(y, x) = [-pi, pi] #define cmpArg [](const auto &p1, const auto &p2) { return atan2l(p1.second, p1.first) < atan2l(p2.second, p2.first); } typedef pair pi; typedef pair pl; #define vl vector #define vvl vector> #define vi vector #define vvi vector> #define vm vector #define vvm vector> #define vvc vector> #define vc vector #define vvpi vector> #define vpi vector #define vpl vector #define vvpl vector> #define pb push_back #define eb emplace_back #define YES cout<<"Yes"<> a; } inline void read(unsigned &a) { std::cin >> a; } inline void read(long &a) { std::cin >> a; } inline void read(long long &a) { std::cin >> a; } inline void read(unsigned long long &a) { std::cin >> a; } inline void read(char &a) { std::cin >> a; } inline void read(float &a) { std::cin >> a; } inline void read(double &a) { std::cin >> a; } inline void read(long double &a) { std::cin >> a; } inline void read(std::vector &vec) { for (int32_t i = 0; i < vec.size(); i++) { int a; read(a); vec[i] = a; } } inline void read(std::string &a) { std::cin >> a; } template inline void read(std::vector &vec); template inline void read(std::array &vec); template inline void read(std::pair &p); template inline void read(T (&vec)[size]); template inline void read(std::vector &vec) { for (auto &i : vec) read(i); } template inline void read(std::deque &vec) { for (auto &i : vec) read(i); } template inline void read(std::array &vec) { for (auto &i : vec) read(i); } template inline void read(std::pair &p) { read(p.first); read(p.second); } template inline void read(T (&vec)[size]) { for (auto &i : vec) read(i); } template inline void read(T &a) { std::cin >> a; } inline void in() {} template inline void in(Head &head, Tail &...tail) { read(head); in(tail...); } inline void print() { std::cout << ' '; } inline void print(const bool &a) { std::cout << a; } inline void print(const int &a) { std::cout << a; } inline void print(const unsigned &a) { std::cout << a; } inline void print(const long &a) { std::cout << a; } inline void print(const long long &a) { std::cout << a; } inline void print(const unsigned long long &a) { std::cout << a; } inline void print(const char &a) { std::cout << a; } inline void print(const char a[]) { std::cout << a; } inline void print(const float &a) { std::cout << a; } inline void print(const double &a) { std::cout << a; } inline void print(const long double &a) { std::cout << a; } inline void print(const std::string &a) { for (auto &&i : a) print(i); } template inline void print(const std::vector &vec); template inline void print(const std::array &vec); template inline void print(const std::pair &p); template inline void print(const T (&vec)[size]); template inline void print(const std::vector &vec) { if (vec.empty()) return; print(vec[0]); for (auto i = vec.begin(); ++i != vec.end();) { std::cout << ' '; print(*i); } } template inline void print(const std::deque &vec) { if (vec.empty()) return; print(vec[0]); for (auto i = vec.begin(); ++i != vec.end();) { std::cout << ' '; print(*i); } } template inline void print(const std::array &vec) { print(vec[0]); for (auto i = vec.begin(); ++i != vec.end();) { std::cout << ' '; print(*i); } } template inline void print(const std::pair &p) { print(p.first); std::cout << ' '; print(p.second); } template inline void print(const T (&vec)[size]) { print(vec[0]); for (auto i = vec; ++i != end(vec);) { std::cout << ' '; print(*i); } } template inline void print(const T &a) { std::cout << a; } inline void out() { std::cout << '\n'; } template inline void out(const T &t) { print(t); std::cout << '\n'; } template inline void out(const Head &head, const Tail &...tail) { print(head); std::cout << ' '; out(tail...); } #define vec(type, name, ...) vector name(__VA_ARGS__); #define vv(type, name, h, ...) std::vector> name(h, std::vector(__VA_ARGS__)); #define INT(...) int32_t __VA_ARGS__; in(__VA_ARGS__) #define LL(...) int64_t __VA_ARGS__; in(__VA_ARGS__) #define ULL(...) uint64_t __VA_ARGS__; in(__VA_ARGS__) #define STR(...) std::string __VA_ARGS__; in(__VA_ARGS__) #define CHR(...) char __VA_ARGS__; in(__VA_ARGS__) #define LD(...) long double __VA_ARGS__; in(__VA_ARGS__) #define VEC(type, name, size) std::vector name(size); in(name) #define VV(type, name, h, w) std::vector> name(h, std::vector(w)); in(name) template ll sum(const T &a) { return accumulate(std::begin(a), std::end(a), 0LL); } template ld dsum(const T &a) { return accumulate(std::begin(a), std::end(a), 0.0L); } template auto min(const T &a) { return *min_element(std::begin(a), std::end(a)); } template auto max(const T &a) { return *max_element(std::begin(a), std::end(a)); } template T floor_div(const T n, const T d) { assert(d != 0); return n / d - static_cast((n ^ d) < 0 && n % d != 0); } template T ceil_div(const T n, const T d) { assert(d != 0); return n / d + static_cast((n ^ d) >= 0 && n % d != 0); } using mint = modint998244353; const ll MAX = 101010; const ll MOD = 998244353; long long fac[MAX], finv[MAX], inv[MAX]; // テーブルを作る前処理 void COMinit() { fac[0] = fac[1] = 1; //累積積 finv[0] = finv[1] = 1; //逆元の累積積 inv[1] = 1; //逆元 for (int i = 2; i < MAX; i++){ fac[i] = fac[i - 1] * i % MOD; inv[i] = MOD - inv[MOD%i] * (MOD / i) % MOD; finv[i] = finv[i - 1] * inv[i] % MOD; } } // 二項係数計算 long long COM(ll n, ll k){ if (n < k) return 0; if (n < 0 || k < 0) return 0; return fac[n] * (finv[k] * finv[n - k] % MOD) % MOD; } long long PER(ll n, ll k) { if(n < k) return 0; if(n < 0 || k < 0) return 0; return (fac[n] * finv[n-k]) % MOD; } mint fastpow(mint a, int b) { mint res = 1; while(b) { if(b&1) res *= a; a *= a; b >>= 1; } return res; } int main() { COMinit(); INT(N,M,K); int ma = M+1; //mexの上界 vvm dp(ma+1,vm(ma+1)); dp[0][0] = 1; rep(now,ma+1) rep(j,ma) REP(nxt,now+1,ma+1) { int pw = min(K-now, nxt-now); pw = max(0,pw); dp[nxt][j+1] += dp[now][j] * fastpow(nxt, pw); } //dp[ma][*]が有効 *-1だけ取らない mint ans = 0; REP(cnt,1,ma+1) { int get = M - (cnt-1); //getこは必ず取っている if(get <= 0) continue; if(get > N) continue; mint sum = 0; for(int i=0,sign=1;i<=get;i++, sign*=-1) sum += fastpow(get-i,N) * COM(get,i) * sign; ans += dp[ma][cnt] * sum; } out(ans.val()); }