Problem: Let's define the function f of multiset a as the multiset of number of occurences of every number, that is present in a.

E.g., f(\{5, 5, 1, 2, 5, 2, 3, 3, 9, 5\}) = \{1, 1, 2, 2, 4\}.

Let's define f^k(a), as applying f to array a k times: f^k(a) = f(f^{k-1}(a)), f^0(a) = a. 

E.g., f^2(\{5, 5, 1, 2, 5, 2, 3, 3, 9, 5\}) = \{1, 2, 2\}.

You are given integers n, k and you are asked how many different values the function f^k(a) can have, where a is arbitrary non-empty array with numbers of size no more than n. Print the answer modulo 998 244 353.

Input

The first and only line of input consists of two integers n, k (1 ≤ n, k ≤ 2020).

Output

Print one number — the number of different values of function f^k(a) on all possible non-empty arrays with no more than n elements modulo 998 244 353.

Examples

Input


3 1


Output


6


Input


5 6


Output


1


Input


10 1


Output


138


Input


10 2


Output


33

Solution (in CPP):

Solution:
#include <bits/stdc++.h>
#pragma comment(linker, "/STACK:1000000000")
#pragma GCC optimize("Ofast,no-stack-protector")
using namespace std;
const int maxn = 2050, mod = 998244353;
int add(int x, int y) {
  x += y;
  if (x >= mod) {
    x -= mod;
  }
  return x;
}
int sub(int x, int y) {
  x -= y;
  if (x < 0) {
    x += mod;
  }
  return x;
}
int mul(int x, int y) { return (long long)x * y % mod; }
int dp[maxn][maxn];
int go(int x, int y) {
  if (x == 0) {
    return 1;
  }
  if (y > x) {
    return dp[x][y] = 1;
  }
  if (dp[x][y] != -1) {
    return dp[x][y];
  }
  return dp[x][y] = add(go(x, y + 1), go(x - y, y));
}
struct vt {
  int pos;
  int x;
  int lim;
  vt() {}
  vt(int pos, int x, int lim) : pos(pos), x(x), lim(lim) {}
};
const int maxsq = 70;
vector<int> dp2[maxsq][maxn];
int go(vt a) {
  a.x = min(a.x, a.lim / a.pos);
  if (dp2[a.pos][a.lim][a.x] != -1) {
    return dp2[a.pos][a.lim][a.x];
  }
  if (a.x == 0) {
    return dp2[a.pos][a.lim][a.x] = 1;
  }
  vt b = a;
  b.x--;
  int ans = go(b);
  b = a;
  if (b.lim >= b.x * b.pos) {
    b.lim -= b.x * b.pos;
    b.pos++;
    ans = add(ans, go(b));
  }
  return dp2[a.pos][a.lim][a.x] = ans;
}
bool check2(vector<int> &a, int lim) {
  int sum = 0;
  for (int i = 0; i < (int)a.size(); i++) {
    sum += a[i] * ((int)a.size() - i);
  }
  return sum <= lim;
}
set<vector<int> > s[maxn];
bool check(vector<int> &a, int k, int lim) {
  if (k == 2) {
    return check2(a, lim);
  } else {
    return s[k].count(a);
  }
}
vector<int> p;
bool good(int k, int lim) {
  vector<int> ch;
  for (int i = (int)p.size() - 1; i >= 0; i--) {
    int x = (int)p.size() - i;
    for (int j = 0; j < p[i]; j++) {
      ch.push_back(x);
    }
  }
  return check(ch, k - 1, lim);
}
bool gen(int k, int lim) {
  if (!good(k, lim)) {
    return false;
  }
  s[k].insert(p);
  int x = (p.empty() ? 1 : p.back());
  while (true) {
    p.push_back(x);
    if (!gen(k, lim)) {
      p.pop_back();
      break;
    }
    p.pop_back();
    x++;
  }
  return true;
}
int main() {
  for (int pos = 1; pos < maxsq; pos++) {
    for (int lim = 0; lim < maxn; lim++) {
      dp2[pos][lim].assign(lim / pos + 1, -1);
    }
  }
  memset(dp, -1, sizeof dp);
  int n, k;
  cin >> n >> k;
  if (k == 2) {
    cout << sub(go({1, n, n}), 1) << '\n';
    return 0;
  } else if (k == 1) {
    cout << sub(go(n, 1), 1) << '\n';
    return 0;
  }
  for (int i = 3; i <= k; i++) {
    gen(i, n);
  }
  cout << sub((int)s[k].size(), 1) << '\n';
}