// Generated by GPT-5 mini #include using namespace std; const int MOD = 998244353; using ll = long long; ll modpow(ll a, ll e=MOD-2) { ll r=1; while(e){ if(e&1) r=r*a%MOD; a=a*a%MOD; e>>=1; } return r; } // NTT implementation (iterative) void ntt(vector& a, bool invert) { int n = a.size(); static vector rev; static vector roots{0,1}; if ((int)rev.size() != n) { int k = __builtin_ctz(n); rev.assign(n,0); for (int i = 0; i < n; ++i) rev[i] = (rev[i>>1]>>1) | ((i&1) << (k-1)); } for (int i = 0; i < n; ++i) if (i < rev[i]) swap(a[i], a[rev[i]]); if ((int)roots.size() < n) { int k = __builtin_ctz(roots.size()); roots.resize(n); while ((1<> (k+1)); for (int i = 1<<(k-1); i < (1<= 0 ? u-v : u-v+MOD; } } } if (invert) { reverse(a.begin()+1, a.end()); ll inv_n = modpow(n); for (int i = 0; i < n; ++i) a[i] = (ll)a[i] * inv_n % MOD; } } vector convolution(const vector& a, const vector& b) { if (a.empty() || b.empty()) return {}; int n = a.size(), m = b.size(); int need = n + m - 1; int sz = 1; while (sz < need) sz <<= 1; vector fa(sz), fb(sz); for (int i = 0; i < n; ++i) fa[i] = a[i]; for (int i = 0; i < m; ++i) fb[i] = b[i]; ntt(fa, false); ntt(fb, false); for (int i = 0; i < sz; ++i) fa[i] = (ll)fa[i] * fb[i] % MOD; ntt(fa, true); fa.resize(need); return fa; } int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int N; long long M; if (!(cin >> N >> M)) return 0; int L = 1< L) { cout << 0 << "\n"; return 0; } // g[k][w] for k from 0..N, but we keep only previous level vector g_prev(2); // k=0, sizes upto 1 g_prev[0] = 1; // 0 W -> "C" g_prev[1] = 1; // 1 W -> "W" for (int k = 1; k <= N; ++k) { // convolution h = g_prev * g_prev vector h = convolution(g_prev, g_prev); // size up to 2*2^{k-1}+1 int maxw = (1< g_cur(maxw+1); // g_cur[0] = h[0] (since allow(0,0)=1) g_cur[0] = h.size() > 0 ? h[0] % MOD : 0; // for w>0: g_cur[w] = h[w] - g_prev[0] * g_prev[w] (g_prev[w] zero if out of range) ll g0 = g_prev.size() > 0 ? g_prev[0] : 0; for (int w = 1; w <= maxw; ++w) { ll val = 0; if (w < (int)h.size()) val = h[w]; ll sub = 0; if (w < (int)g_prev.size()) sub = (ll)g0 * g_prev[w] % MOD; val = (val - sub) % MOD; if (val < 0) val += MOD; g_cur[w] = (int)val; } g_prev.swap(g_cur); } // g_prev is g[N] int patterns = g_prev[L - M]; // multiply by M! * (L-M)! mod vector fact(L+1); fact[0] = 1; for (int i = 1; i <= L; ++i) fact[i] = fact[i-1] * i % MOD; ll ans = patterns; ans = ans * fact[M] % MOD; ans = ans * fact[L - M] % MOD; cout << ans % MOD << "\n"; return 0; }