zscoder has a deck of n+m custom-made cards, which consists of n cards labelled from 1 to n and m jokers. Since zscoder is lonely, he wants to play a game with himself using those cards. 

Initially, the deck is shuffled uniformly randomly and placed on the table. zscoder has a set S which is initially empty. 

Every second, zscoder draws the top card from the deck. 

  * If the card has a number x written on it, zscoder removes the card and adds x to the set S. 
  * If the card drawn is a joker, zscoder places all the cards back into the deck and reshuffles (uniformly randomly) the n+m cards to form a new deck (hence the new deck now contains all cards from 1 to n and the m jokers). Then, if S currently contains all the elements from 1 to n, the game ends. Shuffling the deck doesn't take time at all. 



What is the expected number of seconds before the game ends? We can show that the answer can be written in the form P/Q where P, Q are relatively prime integers and Q ≠ 0 mod 998244353. Output the value of (P ⋅ Q^{-1}) modulo 998244353.

Input

The only line of the input contains two integers n and m (1 ≤ n, m ≤ 2 ⋅ 10^{6}).

Output

Output a single integer, the value of (P ⋅ Q^{-1}) modulo 998244353.

Examples

Input


2 1


Output


5


Input


3 2


Output


332748127


Input


14 9


Output


969862773

Note

For the first sample, it can be proven that the expected time before the game ends is 5 seconds.

For the second sample, it can be proven that the expected time before the game ends is 28/3 seconds.
#include <bits/stdc++.h>
using namespace std;
void FAST() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
}
long long Rselect(vector<long long> v, long long i, long long l, long long r);
long long partition(vector<long long> v, long long l, long long r);
void scanc(vector<char>& v, long long n) {
  for (long long i = 0; i < n; i++) {
    char num;
    cin >> num;
    v.push_back(num);
  }
}
void scanP(vector<pair<long long, long long> >& v, long long n) {
  for (long long i = 0; i < n; i++) {
    long long num1, num2;
    cin >> num1 >> num2;
    pair<long long, long long> p = {num1, num2};
    v.push_back(p);
  }
}
template <typename T>
ostream& operator<<(ostream& stream, const vector<T>& vec) {
  for (auto& i : vec) {
    stream << i << ' ';
  }
  stream << '\n';
  return stream;
}
template <class T>
istream& operator>>(istream& stream, vector<T>& vec) {
  for (auto& i : vec) {
    stream >> i;
  }
  return stream;
}
void solve();
void scanN(vector<long long>& v, long long n) {
  for (long long i = 0; i < n; i++) {
    int num;
    cin >> num;
    v.push_back(num);
  }
}
void scans(vector<string>& v, long long n) {
  for (long long i = 0; i < n; i++) {
    string s;
    cin >> s;
    v.push_back(s);
  }
}
long long modfactorial(long long n, long long p) {
  if (n >= p) return 0;
  long long result = 1;
  for (long long i = 1; i < n + 1; i++) {
    result = result * i;
    result = result % p;
  }
  return result;
}
long long MI(long long a, long long b, long long s0 = 1, long long s1 = 0) {
  long long k = b;
  if (b == 0)
    return s0;
  else {
    return MI(b, a % b, s1, s0 - s1 * (a / b));
  }
}
long long choose(long long a, long long b, long long c) {
  if (a < b) return 0;
  long long x = modfactorial(a, c);
  long long y = modfactorial(b, c);
  long long z = modfactorial(a - b, c);
  long long y_ = MI(y, c, 1, 0);
  if (y_ < 0) y_ = y_ + c;
  long long z_ = MI(z, c, 1, 0);
  if (z_ < 0) z_ = z_ + c;
  long long mul = (x * y_) % c;
  mul = (mul * z_) % c;
  return mul;
}
void SOLT() {
  int test;
  cin >> test;
  while (test--) {
    solve();
  }
}
long long modpow(long long n, long long p, long long k) {
  n = n % k;
  long long res = 1;
  while (p > 0) {
    if (p % 2 == 1) res = res * n % k;
    n = n * n % k;
    p = p / 2;
  }
  return res;
}
bool isPrime(long long a) {
  for (long long i = 2; i * i <= a; ++i)
    if (a % i == 0) return false;
  return true;
}
bool useflushdivisible(long long a) {
  cout << a << endl;
  fflush(stdout);
  char sl[10];
  scanf("%s", sl);
  return sl[0] == 'y' || sl[0] == 'Y';
}
long long phi(long long n) {
  long long result = n;
  for (long long i = 2; i * i <= n; i++) {
    if (n % i == 0) {
      while (n % i == 0) n = n / i;
      result = result - result / i;
    }
  }
  if (n > 1) result = result - result / n;
  return result;
}
bool cmp(pair<long long, long long> x, pair<long long, long long> y) {
  return x.second < y.second;
}
int main() {
  FAST();
  srand(time(0));
  int test = 1;
  for (int tt = 1; tt <= test; tt++) solve();
  return 0;
}
void solve() {
  long long n, m;
  cin >> n >> m;
  long long ans = 0;
  for (long long i = 1; i < n + 1; i++) {
    ans += MI(i, 998244353);
  }
  while (ans < 0) ans += 998244353;
  ans *= m;
  ans %= 998244353;
  ans += 1;
  ans %= 998244353;
  long long ans1 = MI(m + 1, 998244353);
  if (ans1 < 0) ans1 += 998244353;
  ans1 *= n;
  ans1 %= 998244353;
  ans1 += 1;
  ans1 %= 998244353;
  ans *= ans1;
  ans %= 998244353;
  cout << ans << endl;
}
long long Rselect(vector<long long> v, long long i, long long l, long long r) {
  if (l == r) return v[l];
  long long pivot = partition(v, l, r);
  if (pivot == i)
    return v[pivot - 1];
  else if (pivot < i) {
    return Rselect(v, i, pivot, r);
  } else {
    return Rselect(v, i, l, pivot - 2);
  }
}
long long partition(vector<long long> v, long long l, long long r) {
  long long pivot_index = rand() % (r - l + 1) + l;
  swap(v[pivot_index], v[l]);
  long long i = l + 1, j = l + 1;
  while (j <= r) {
    if (v[j] < v[l]) {
      swap(v[j], v[i]);
      i++;
    }
    j++;
  }
  swap(v[l], v[i - 1]);
  return i;
}
