// Original C++ solution (slower):
#include <bits/stdc++.h>



using std::pair;

using std::vector;

using std::string;



typedef long long ll;

typedef pair<int, int> pii;



#define fst first

#define snd second

#define pb(a) push_back(a)

#define mp(a, b) std::make_pair(a, b)

#define debug(...) fprintf(stderr, __VA_ARGS__)



template <typename T> bool chkmax(T& a, T b) { return a < b ? a = b, 1 : 0; }

template <typename T> bool chkmin(T& a, T b) { return a > b ? a = b, 1 : 0; }



const int oo = 0x3f3f3f3f;



string procStatus() {

    std::ifstream t("/proc/self/status");

    return string(std::istreambuf_iterator<char>(t), std::istreambuf_iterator<char>());

}



template <typename T> T read(T& x) {

    int f = 1; x = 0;

    char ch = getchar();

    for(;!isdigit(ch); ch = getchar()) if(ch == '-') f = -1;

    for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;

    return x *= f;

}



const int M = 200;

const int N = 20000;

const int mo = 998244353;



int fpm(int x, int y) {

    int res = 1;

    for(; y > 0; y >>= 1) {

        if(y & 1)

            res = (ll) res * x % mo;

        x = (ll) x * x % mo;

    }

    return res;

}



namespace Poly {

    const int g = 3;



    int n;

    inline void init(int len) {

        n = len;

        while(n != (n & -n)) n += (n & -n);

    }



    void dft(int *x, int ty) {

        for(int i = 0, j = 0; i < n; ++i) {

            if(i < j) std::swap(x[i], x[j]);

            for(int l = n >> 1; (j ^= l) < l; l >>= 1);

        }



        for(int l = 1; l < n; l <<= 1) {

            int wn = fpm(g, (mo - 1) / 2 / l);

            if(ty == -1) wn = fpm(wn, mo - 2);



            for(int i = 0; i < n; i += (l << 1)) {

                int w = 1;

                for(int j = 0; j < l; ++j) {

                    int u = x[i + j];

                    int v = (ll) x[i + j + l] * w % mo;



                    w = (ll) w * wn % mo;

                    x[i + j] = (u + v) % mo;

                    x[i + j + l] = (u - v + mo) % mo;

                }

            }

        }



        if(ty == -1) {

            int invn = fpm(n, mo - 2);

            for(int i = 0; i < n; ++i) {

                x[i] = (ll) x[i] * invn % mo;

            }

        }

    }

}



int n, m;

int f[N + 5][M + 5];

int fac[N + 5], inv[N + 5];



void init() {

    fac[0] = 1;

    for(int i = 1; i <= N; ++i) fac[i] = (ll) fac[i-1] * i % mo;

    inv[N] = fpm(fac[N], mo - 2);

    for(int i = N; i >= 1; --i) inv[i-1] = (ll) inv[i] * i % mo;

}



inline int binom(int x, int y) {

    if(x < 0 || y < 0 || x < y) return 0;

    return (ll) fac[x] * inv[y] % mo * inv[x-y] % mo;

}



int main() {

#ifdef Wearry

    freopen("in", "r", stdin);

    freopen("out", "w", stdout);

#endif



    init();

    read(n), read(m); 



    f[0][0] = 1;

    Poly::init(2*n + 1);



    static int tx[N + 5], ty[N + 5];



    for(int j = 1; j <= m; ++j) {

        for(int i = 0; i < Poly::n; ++i) tx[i] = i <= n ? (ll) f[i][j-1] * inv[i] % mo : 0;

        for(int i = 0; i < Poly::n; ++i) ty[i] = (3 <= i && i <= n + 2) ? inv[i] : 0;



        Poly::dft(tx, +1);

        Poly::dft(ty, +1);



        for(int i = 0; i < Poly::n; ++i) tx[i] = (ll) tx[i] * ty[i] % mo;



        Poly::dft(tx, -1);



        for(int i = 0; i <= n; ++i) {

            f[i][j] = (f[i][j] + (ll) (binom(i + 1, 2) + 1) * f[i][j-1]) % mo;

            f[i][j] = (f[i][j] + (ll) tx[i + 2] * fac[i + 2]) % mo;

        }

    }



    int ans = 0;

    for(int i = 0; i <= n; ++i) {

        ans = (ans + (ll) binom(n, i) * f[i][m]) % mo;

    }

    printf("%d\n", ans);



    return 0;

}


// Optimized solution to the same problem (faster):
#include <bits/stdc++.h>



using std::pair;

using std::vector;

using std::string;



typedef long long ll;

typedef pair<int, int> pii;



#define fst first

#define snd second

#define pb(a) push_back(a)

#define mp(a, b) std::make_pair(a, b)

#define debug(...) fprintf(stderr, __VA_ARGS__)



template <typename T> bool chkmax(T& a, T b) { return a < b ? a = b, 1 : 0; }

template <typename T> bool chkmin(T& a, T b) { return a > b ? a = b, 1 : 0; }



const int oo = 0x3f3f3f3f;



string procStatus() {

    std::ifstream t("/proc/self/status");

    return string(std::istreambuf_iterator<char>(t), std::istreambuf_iterator<char>());

}



template <typename T> T read(T& x) {

    int f = 1; x = 0;

    char ch = getchar();

    for(;!isdigit(ch); ch = getchar()) if(ch == '-') f = -1;

    for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;

    return x *= f;

}



const int M = 200;

const int N = 8005;

const int mo = 998244353;



int fpm(int x, int y) {

    int res = 1;

    for(; y > 0; y >>= 1) {

        if(y & 1)

            res = (ll) res * x % mo;

        x = (ll) x * x % mo;

    }

    return res;

}



namespace Poly {



    const int g = 3;



    int n;

    inline void init(int len) {

        n = len;

        while(n != (n & -n)) n += (n & -n);

    }



    void dft(int *x, int ty) {

        for(int i = 0, j = 0; i < n; ++i) {

            if(i < j) std::swap(x[i], x[j]);

            for(int l = n >> 1; (j ^= l) < l; l >>= 1);

        }



        for(int l = 1; l < n; l <<= 1) {

            int wn = fpm(g, (mo - 1) / 2 / l);

            if(ty == -1) wn = fpm(wn, mo - 2);



            for(int i = 0; i < n; i += (l << 1)) {

                int w = 1, *u = x + i, *v = x + i + l;

                for(int j = 0; j < l; ++j) {

                    int t0 = (*u + (ll) *v * w) % mo;

                    int t1 = (*u - (ll) *v * w) % mo;



                    *u = t0, *v = t1;

                    w = (ll) w * wn % mo;

                    ++ u, ++ v;

                }

            }

        }



        if(ty == -1) {

            int invn = fpm(n, mo - 2);

            for(int i = 0; i < n; ++i) {

                x[i] = (ll) x[i] * invn % mo;

            }

        }

    }

}



int n, m;

int f[N + 5][M + 5];

int fac[N + 5], inv[N + 5];



void init() {

    fac[0] = 1;

    for(int i = 1; i <= N; ++i) fac[i] = (ll) fac[i-1] * i % mo;

    inv[N] = fpm(fac[N], mo - 2);

    for(int i = N; i >= 1; --i) inv[i-1] = (ll) inv[i] * i % mo;

}



inline int binom(int x, int y) {

    if(x < 0 || y < 0 || x < y) return 0;

    return (ll) fac[x] * inv[y] % mo * inv[x-y] % mo;

}



int main() {

#ifdef Wearry

    freopen("in", "r", stdin);

    freopen("out", "w", stdout);

#endif



    init();

    read(n), read(m); 



    f[0][0] = 1;

    Poly::init(2*n + 3);



    static int tx[(N<<2) + 5], ty[(N<<2) + 5];



    for(int j = 1; j <= m; ++j) {

        for(int i = 0; i < Poly::n; ++i) tx[i] = i <= n ? (ll) f[i][j-1] * inv[i] % mo : 0;

        for(int i = 0; i < Poly::n; ++i) ty[i] = (3 <= i && i <= n + 2) ? inv[i] : 0;



        Poly::dft(tx, +1);

        Poly::dft(ty, +1);



        for(int i = 0; i < Poly::n; ++i) tx[i] = (ll) tx[i] * ty[i] % mo;



        Poly::dft(tx, -1);



        for(int i = 0; i <= n; ++i) {

            f[i][j] = (f[i][j] + (ll) (binom(i + 1, 2) + 1) * f[i][j-1]) % mo;

            f[i][j] = (f[i][j] + (ll) tx[i + 2] * fac[i + 2]) % mo;

        }

    }



    int ans = 0;

    for(int i = 0; i <= n; ++i) {

        ans = (ans + (ll) binom(n, i) * f[i][m]) % mo;

    }

    printf("%d\n", (ans + mo) % mo);



    return 0;

}


// Fastest known solution for this problem: