#include using namespace std; typedef long long ll; long long MOD = 998244353; static const int MAXN = 2500000; // 必要に応じて大きく設定 // 階乗・階乗逆元の配列 static long long fact[MAXN+1], invFact[MAXN+1]; // 繰り返し二乗法 (a^b mod M) long long modpow(long long a, long long b, long long M) { long long ret = 1 % M; a %= M; while (b > 0) { if (b & 1) ret = (ret * a) % M; a = (a * a) % M; b >>= 1; } return ret; } // 前処理: 階乗と逆元のテーブルを作る void initFactorials() { // 階乗テーブル fact[0] = 1; for (int i = 1; i <= MAXN; i++) { fact[i] = fact[i-1] * i % MOD; } // 階乗逆元テーブル invFact[MAXN] = modpow(fact[MAXN], MOD - 2, MOD); // フェルマーの小定理で逆元を計算 for (int i = MAXN; i >= 1; i--) { invFact[i-1] = invFact[i] * i % MOD; } } // 組み合わせ数 C(n, r) long long comb(int n, int r) { if (r < 0 || r > n) return 0; return fact[n] * invFact[r] % MOD * invFact[n - r] % MOD; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); ll n, k; cin >> n >> k; if (k > n - k) k = n - k; if (k < 100000000) { ll ans = 1; const ll mod = 998244353; ll temp = 1; if (k > n - k) k = n - k; for (ll i = 1; i <= k; ++i) { ans = ans * ((n - i + 1) % mod) % mod; temp = temp * i % mod; } ans = ans * modpow(temp, mod - 2, mod) % mod; cout << ans << '\n'; return 0; } vector prev(11); prev[0] = 1; prev[1] = 808258749; prev[2] = 117153405; prev[3] = 761699708; prev[4] = 573994984; prev[5] = 62402409; prev[6] = 511621808; prev[7] = 242726978; prev[8] = 887890124; prev[9] = 875880304; prev[10] = 0; ll ans = prev[n / 100000000]; const ll mod = 998244353; for (ll i = (n / 100000000) * 100000000 + 1; i <= n; ++i) { ans = ans * i % mod; } ll temp = prev[k / 100000000]; for (ll i = (k / 100000000) * 100000000 + 1; i <= k; ++i) { temp = temp * i % mod; } ans = ans * modpow(temp, mod - 2, mod) % mod; temp = prev[(n - k) / 100000000]; for (ll i = ((n - k) / 100000000) * 100000000 + 1; i <= n - k; ++i) { temp = temp * i % mod; } ans = ans * modpow(temp, mod - 2, mod) % mod; cout << ans << '\n'; }