#include <bits/stdc++.h>
const int inf = 0x3f3f3f3f, Inf = 0x7fffffff;
const long long INF = 0x3f3f3f3f3f3f3f3f;
__inline__ __attribute__((always_inline)) unsigned int rnd() {
  static unsigned int seed = 416;
  return seed ^= seed >> 5, seed ^= seed << 17, seed ^= seed >> 13;
}
template <typename _Tp>
_Tp gcd(const _Tp &a, const _Tp &b) {
  return (!b) ? a : gcd(b, a % b);
}
template <typename _Tp>
__inline__ __attribute__((always_inline)) _Tp abs(const _Tp &a) {
  return a >= 0 ? a : -a;
}
template <typename _Tp>
__inline__ __attribute__((always_inline)) _Tp max(const _Tp &a, const _Tp &b) {
  return a < b ? b : a;
}
template <typename _Tp>
__inline__ __attribute__((always_inline)) _Tp min(const _Tp &a, const _Tp &b) {
  return a < b ? a : b;
}
template <typename _Tp>
__inline__ __attribute__((always_inline)) void chmax(_Tp &a, const _Tp &b) {
  (a < b) && (a = b);
}
template <typename _Tp>
__inline__ __attribute__((always_inline)) void chmin(_Tp &a, const _Tp &b) {
  (b < a) && (a = b);
}
template <typename _Tp>
__inline__ __attribute__((always_inline)) void read(_Tp &x) {
  char ch(getchar());
  bool f(false);
  while (ch < 48 || ch > 57) f |= ch == 45, ch = getchar();
  x = ch & 15, ch = getchar();
  while (ch >= 48 && ch <= 57)
    x = (((x << 2) + x) << 1) + (ch & 15), ch = getchar();
  if (f) x = -x;
}
template <typename _Tp, typename... Args>
__inline__ __attribute__((always_inline)) void read(_Tp &t, Args &...args) {
  read(t);
  read(args...);
}
template <typename _Tp, typename... Args>
__inline__ __attribute__((always_inline)) _Tp min(const _Tp &a, const _Tp &b,
                                                  const Args &...args) {
  return a < b ? min(a, args...) : min(b, args...);
}
template <typename _Tp, typename... Args>
__inline__ __attribute__((always_inline)) _Tp max(const _Tp &a, const _Tp &b,
                                                  const Args &...args) {
  return a < b ? max(b, args...) : max(a, args...);
}
__inline__ __attribute__((always_inline)) int read_str(char *s) {
  char ch(getchar());
  while (ch == ' ' || ch == '\r' || ch == '\n') ch = getchar();
  char *tar = s;
  *tar = ch, ch = getchar();
  while (ch != ' ' && ch != '\r' && ch != '\n' && ch != EOF)
    *(++tar) = ch, ch = getchar();
  return tar - s + 1;
}
const int N = 4000005;
const int mod = 998244353;
template <typename _Tp1, typename _Tp2>
__inline__ __attribute__((always_inline)) void add(_Tp1 &a, _Tp2 b) {
  (a += b) >= mod && (a -= mod);
}
template <typename _Tp1, typename _Tp2>
__inline__ __attribute__((always_inline)) void sub(_Tp1 &a, _Tp2 b) {
  (a -= b) < 0 && (a += mod);
}
long long ksm(long long a, long long b = mod - 2) {
  long long res = 1;
  while (b) {
    if (b & 1) res = res * a % mod;
    a = a * a % mod, b >>= 1;
  }
  return res;
}
long long fac[N], inv[N], ifac[N];
void init() {
  fac[0] = fac[1] = inv[0] = inv[1] = ifac[0] = ifac[1] = 1;
  for (int i = 2; i < N; ++i) {
    fac[i] = fac[i - 1] * i % mod;
    inv[i] = inv[mod % i] * (mod - mod / i) % mod;
    ifac[i] = ifac[i - 1] * inv[i] % mod;
  }
}
__inline__ __attribute__((always_inline)) long long C(int n, int m) {
  if (n < m) return 0;
  return fac[n] * ifac[m] % mod * ifac[n - m] % mod;
}
long long f[N];
long long s1[N], s2[N], s3[N];
int main() {
  init();
  long long n, m;
  read(n, m);
  for (int i = 0; i <= n; ++i) {
    if (i) s1[i] = s1[i - 1];
    add(s1[i], fac[m + i - 1] * ifac[i] % mod);
    if (i) s2[i] = s2[i - 1], add(s2[i], fac[m + i - 1] * ifac[i - 1] % mod);
    long long _ = m * fac[i] % mod * fac[n - i] % mod * ifac[n + m] % mod;
    long long tmp = _ * C(n + m + 1, m + i + 1) % mod *
                    (s1[i] * (i + 1) % mod - s2[i] + mod) % mod;
    long long coef =
        (mod + 1 -
         _ * C(n + m, m + i) % mod * ifac[i] % mod * fac[m + i - 1] % mod);
    f[i] = (tmp + _ * C(n + m, m + i) % mod * s3[i] % mod) * ksm(coef) % mod;
    s3[i + 1] = s3[i],
           add(s3[i + 1], fac[m + i - 1] * ifac[i] % mod * f[i] % mod);
  }
  printf("%lld\n", f[n]);
  return 0;
}
