Problem:
Score : 1800 points

Problem Statement

We have an N \times M grid. The square at the i-th row and j-th column will be denoted as (i,j).
Particularly, the top-left square will be denoted as (1,1), and the bottom-right square will be denoted as (N,M).
Takahashi painted some of the squares (possibly zero) black, and painted the other squares white.

We will define an integer sequence A of length N, and two integer sequences B and C of length M each, as follows:

A_i(1\leq i\leq N) is the minimum j such that (i,j) is painted black, or M+1 if it does not exist.

B_i(1\leq i\leq M) is the minimum k such that (k,i) is painted black, or N+1 if it does not exist.

C_i(1\leq i\leq M) is the maximum k such that (k,i) is painted black, or 0 if it does not exist.

How many triples (A,B,C) can occur? Find the count modulo 998244353.

Notice

In this problem, the length of your source code must be at most 20000 B.
Note that we will invalidate submissions that exceed the maximum length.

Constraints

1 \leq N \leq 8000

1 \leq M \leq 200

N and M are integers.

Partial Score

1500 points will be awarded for passing the test set satisfying N\leq 300.

Input

Input is given from Standard Input in the following format:

N M

Output

Print the number of triples (A,B,C), modulo 998244353.

Sample Input 1

2 3

Sample Output 1

64

Since N=2, given B_i and C_i, we can uniquely determine the arrangement of black squares in each column.
For each i, there are four possible pairs (B_i,C_i): (1,1), (1,2), (2,2) and (3,0). Thus, the answer is 4^M=64.

Sample Input 2

4 3

Sample Output 2

2588

Sample Input 3

17 13

Sample Output 3

229876268

Sample Input 4

5000 100

Sample Output 4

57613837

Solution in C++ (GCC 5.4.1) (judge verdict: Runtime Error)

#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;

const int N=8e3+5;
const int M=2e2+5;
const int mod=998244353;
int n,m,f[N<<2],g1[N<<2],g2[N<<2],fac[N],inv[N],dp[N][M];

inline int mul(int x,int y) {return 1ll*x*y%mod;}
template <typename _Tp> inline void IN(_Tp&x) {
    char ch;bool flag=0;x=0;
    while(ch=getchar(),!isdigit(ch)) if(ch=='-') flag=1;
    while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
    if(flag) x=-x;
}

namespace Poly {
    int filp[N<<1];
    inline int modpow(int x,int y,int res=1) {
        for(;y;y>>=1,x=mul(x,x)) if(y&1) res=mul(res,x);
        return res;
    }
    inline void NTT(int*f,int limit,short inv) {
        for(int i=0;i<limit;++i) if(i<filp[i]) swap(f[i],f[filp[i]]);
        for(int p=2;p<=limit;p<<=1) {
            int len=p>>1,tmp=modpow(3,(mod-1)/p);
            for(int k=0;k<limit;k+=p) {
                int buf=1;
                for(int l=k;l<k+len;++l,buf=mul(buf,tmp)) {
                    int t=mul(f[l+len],buf);
                    f[l+len]=(f[l]-t+mod)%mod,f[l]=(f[l]+t)%mod;
                }
            }
        }
        if(inv==1) return;
        int sl=modpow(limit,mod-2);reverse(f+1,f+limit);
        for(int i=0;i<limit;++i) f[i]=1ll*f[i]*sl%mod;
    }
}using namespace Poly;

int limit=1,cnt=0;
inline int C(int n,int m) {return mul(fac[n],mul(inv[m],inv[n-m]));}
inline void solve(int j) {
    memset(g1,0,sizeof(g1));
    memset(g2,0,sizeof(g2));
	for(int i=1;i<=n;++i) g1[i]=inv[i+2];
	for(int i=0;i<=n;++i) g2[i]=mul(dp[i][j-1],inv[i]);
	for(int i=0;i<=n;++i) dp[i][j]=(dp[i][j]+mul(dp[i][j-1],(1+i+C(i,2))%mod))%mod;
	NTT(g1,limit,1),NTT(g2,limit,1);
	for(int i=0;i<limit;++i) f[i]=mul(g1[i],g2[i]);
	NTT(f,limit,-1);
	for(int i=1;i<=n;++i) dp[i][j]=(dp[i][j]+mul(f[i],fac[i+2]))%mod;
}

int main() {
    IN(n),IN(m),fac[0]=inv[0]=1;
	for(int i=1;i<=n+2;++i) fac[i]=mul(fac[i-1],i);
	for(int i=1;i<=n+2;++i) inv[i]=modpow(fac[i],mod-2);
	while(limit<((n+1)<<1)) limit<<=1,++cnt;
	for(int i=0;i<limit;++i) filp[i]=(filp[i>>1]>>1)|((i&1)<<(cnt-1));
	dp[0][0]=1;
	for(int j=1;j<=m;++j) solve(j);
	int ans=0;
	for(int i=0;i<=n;++i) ans=(ans+mul(C(n,i),dp[i][m]))%mod;
	printf("%d\n",(ans+mod)%mod);
	return 0;
}