#include #include //小数点出力用 //cout << fixed << setprecision(10) << ans; #include #include #include #include #include #include #include #include using ll = long long; using namespace std; #define modPHash (ll)((1LL<<61)-1) #define modP (ll)998244353 bool chkrng0idx(int pos, int sup) { return (0 <= pos && pos < sup); } int clk4(int num) { return (num - 2) * (num % 2); } void yn(bool tf) { cout << (tf ? "YES\n" : "NO\n"); } /* 使い方:はじめにgenTwiddleを行って下さい。畳み込みの回転子の前計算です。 */ long long modpow998244353(long long b, long long e) { int i; ll tmp = 1; for (i = 0; tmp <= e; i++) { tmp <<= 1; } tmp >>= 1; i--; ll ans = 1; for (; i >= 0; i--) { ans = (long long)ans * (long long)ans; ans %= 998244353; if ((e >> i) % 2 == 1) { ans *= b; ans %= 998244353; } tmp >>= 1; } return ans; } long long inverse_mod998244353(long long X) { return modpow998244353(X, 998244351); } int scaleW[23]; int invscaleW[23]; void genTwiddle() { scaleW[22] = modpow998244353(3, 119); for (int i = 21;i >= 0;i--) { scaleW[i] = ((long long)scaleW[i + 1] * (long long)scaleW[i + 1]) % 998244353LL; } for (int i = 0;i <= 22;i++) { invscaleW[i] = inverse_mod998244353(scaleW[i]); } } void NTT(vector& calc_tmp) { int i, j; long long tmpl, tmpr; long long rot = 1; int divCnt = 1; while (calc_tmp.size() > (1 << divCnt))divCnt++; calc_tmp.resize(1 << divCnt); for (int b = divCnt - 1;b >= 0;b--) { for (int i = 0;i < (1 << divCnt);) { if ((i >> b) & 1) { i += (1 << b); rot = 1; } else { j = i + (1 << b); tmpl = calc_tmp[i]; tmpr = calc_tmp[j]; if (tmpl + tmpr >= 998244353)calc_tmp[i] = tmpl + tmpr - 998244353; else calc_tmp[i] = tmpl + tmpr; if (tmpl - tmpr >= 0)calc_tmp[j] = tmpl - tmpr; else calc_tmp[j] = tmpl - tmpr + 998244353; calc_tmp[j] = ((long long)calc_tmp[j] * rot) % 998244353LL; rot = (rot * (long long)scaleW[b]) % 998244353LL; i++; } } } } void INTT(vector& calc_tmp) { int i, j; long long tmpl, tmpr; long long rot = 1; int divCnt = 1; while (calc_tmp.size() > (1 << divCnt))divCnt++; for (int b = 0;b < divCnt;b++) { for (int i = 0;i < (1 << divCnt);) { if ((i >> b) & 1) { i += (1 << b); rot = 1; } else { j = i + (1 << b); calc_tmp[j] = (calc_tmp[j] * rot) % 998244353LL; tmpl = calc_tmp[i]; tmpr = calc_tmp[j]; if (tmpl + tmpr >= 998244353)calc_tmp[i] = tmpl + tmpr - 998244353; else calc_tmp[i] = tmpl + tmpr; if (tmpl - tmpr >= 0)calc_tmp[j] = tmpl - tmpr; else calc_tmp[j] = tmpl - tmpr + 998244353; rot = (rot * (long long)invscaleW[b]) % 998244353LL; i++; } } } ll tmpInv = inverse_mod998244353(1 << divCnt); for (i = 0;i < (1 << divCnt);i++) { calc_tmp[i] = ((long long)calc_tmp[i] * tmpInv) % 998244353LL; } } vector convolution(vector A, vector B) { int Ssize = A.size() + B.size(); A.resize(Ssize); B.resize(Ssize); NTT(A); NTT(B); for (int i = A.size() - 1;i >= 0;i--) { A[i] = ((long long)A[i] * (long long)B[i]) % 998244353LL; } INTT(A); A.resize(Ssize); return A; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); genTwiddle(); int N; cin >> N; int M; cin >> M; if (N == 0) { cout << 1; return 0; } int Q = M; int D = (1 << N) - M; vectordp[19]; ll fact[1010000]; fact[0] = 1; for (ll i = 1;i < 1010000;i++) { fact[i] = fact[i - 1] * i; fact[i] %= modP; } dp[0] = vector(2, 1); for (int i = 1;i <= N;i++) { dp[i] = convolution(dp[i - 1], dp[i - 1]); dp[i].resize((1 << i) + 1); for (int j = 1;j < dp[i - 1].size();j += 1) { dp[i][j] -= dp[i - 1][j]; dp[i][j] += modP; dp[i][j] %= modP; } } ll ans = (ll)dp[N][D] * fact[D]; ans %= modP; ans *= fact[Q]; ans %= modP; cout << ans; return 0; }