Problem: Let n be an integer. Consider all permutations on integers 1 to n in lexicographic order, and concatenate them into one big sequence P. For example, if n = 3, then P = [1, 2, 3, 1, 3, 2, 2, 1, 3, 2, 3, 1, 3, 1, 2, 3, 2, 1]. The length of this sequence is n ⋅ n!.

Let 1 ≤ i ≤ j ≤ n ⋅ n! be a pair of indices. We call the sequence (P_i, P_{i+1}, ..., P_{j-1}, P_j) a subarray of P. 

You are given n. Find the number of distinct subarrays of P. Since this number may be large, output it modulo 998244353 (a prime number). 

Input

The only line contains one integer n (1 ≤ n ≤ 10^6), as described in the problem statement.

Output

Output a single integer — the number of distinct subarrays, modulo 998244353.

Examples

Input


2


Output


8


Input


10


Output


19210869

Note

In the first example, the sequence P = [1, 2, 2, 1]. It has eight distinct subarrays: [1], [2], [1, 2], [2, 1], [2, 2], [1, 2, 2], [2, 2, 1] and [1, 2, 2, 1]. 

Solution (in CPP):

Solution:
#include <bits/stdc++.h>
using namespace std;
struct Timer {
  chrono::time_point<chrono::high_resolution_clock> start, end;
  chrono::duration<float> dur;
  Timer() { start = chrono::high_resolution_clock::now(); }
  ~Timer() {
    end = chrono::high_resolution_clock::now();
    dur = end - start;
    cout << "\nTime Elapsed : " << dur.count() << " s\n";
  }
};
long long int sum() { return 0; }
template <typename T, typename... Args>
T sum(T a, Args... args) {
  return a + sum(args...);
}
template <int D, typename T>
struct Vec : public vector<Vec<D - 1, T>> {
  static_assert(D >= 1, "Vector dimension must be greater than zero!");
  template <typename... Args>
  Vec(int n = 0, Args... args)
      : vector<Vec<D - 1, T>>(n, Vec<D - 1, T>(args...)) {}
};
template <typename T>
struct Vec<1, T> : public vector<T> {
  Vec(int n = 0, T val = T()) : vector<T>(n, val) {}
};
template <typename T>
class SieveEratosthenes {
 public:
  vector<T> primes;
  vector<bool> is_prime;
  SieveEratosthenes(int MAX = 1000000) {
    is_prime.resize(MAX + 1, true);
    is_prime[0] = is_prime[1] = false;
    for (long long int i = 2; i * i <= MAX; i++)
      if (is_prime[i])
        for (long long int j = i * i; j <= MAX; j += i) is_prime[j] = false;
    for (long long int i = 2; i <= MAX; i++)
      if (is_prime[i]) primes.push_back(i);
  }
};
template <typename T>
class SieveEuler {
 public:
  vector<T> primes;
  vector<T> lp;
  inline SieveEuler(int MAX = 1000000) {
    lp.resize(MAX + 1, 0);
    for (long long int i = 2; i <= MAX; i++) {
      if (lp[i] == 0) {
        lp[i] = i;
        primes.push_back(i);
      }
      for (int j = 0;
           j < primes.size() && i * primes[j] <= MAX && primes[j] <= lp[i];
           ++j) {
        if (primes[j] == lp[i]) {
          lp[i * primes[j]] = primes[j];
        } else {
          lp[i * primes[j]] = primes[j];
        }
      }
    }
  }
};
long long int EulerPhi(long long int n) {
  long long int result = n;
  for (long long int i = 2; i * i <= n; i++) {
    if (n % i == 0) {
      while (n % i == 0) n /= i;
      result -= result / i;
    }
  }
  if (n > 1) result -= result / n;
  return result;
}
template <typename T>
vector<vector<T>> matmul(const vector<vector<T>>& a,
                         const vector<vector<T>>& b) {
  int n = a.size(), m = b[0].size(), k = b.size();
  vector<vector<T>> c(n, vector<T>(m));
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      for (int l = 0; l < k; l++) c[i][j] += (a[i][k] * b[k][j]);
    }
  }
  return c;
}
template <typename T>
T extended_euclid(T a, T b, vector<T>& X) {
  if (b == 0) {
    X = {1, 0};
    return a;
  } else {
    T g = extended_euclid(b, a % b, X);
    vector<vector<T>> G = {{0LL, 1LL}, {1LL, -(a / b)}};
    X = matmul<T>(G, X);
    return g;
  }
}
template <typename T>
bool isPrime(T n) {
  if (n <= 1)
    return false;
  else if (n == 2 || n == 3)
    return true;
  else if (n % 2 == 0 || n % 3 == 0)
    return false;
  T x = 5;
  T p = 2;
  while (x * x <= n) {
    if (n % x == 0) return true;
    x += p;
    p = 6 - p;
  }
  return true;
}
long long int binpow(long long int x, long long int n,
                     long long int mod = 1000000007) {
  long long int ans = 1;
  x = x % mod;
  while (n >= 1) {
    if (n & 1) ans = (ans * x) % mod;
    x = (x * x) % mod;
    n >>= 1;
  }
  return ans;
}
long long int gcd(long long int a, long long int b) {
  if (b == 0)
    return a;
  else
    return gcd(b, a % b);
}
template <typename T>
class Graph {
 public:
  int n;
  vector<vector<T>> adj;
  bool directed;
  Graph(int n, bool directed = false) {
    this->n = n;
    adj.resize(n + 1);
    this->directed = directed;
  }
  void add_edge(int u, int v) {
    adj[u].push_back(v);
    if (!directed) adj[v].push_back(u);
  }
  void add_edge(int u, int v, int w) {
    adj[u].push_back({v, w});
    if (!directed) adj[v].push_back({u, w});
  }
};
class DisjointSets {
 public:
  int n;
  vector<int> parent;
  vector<int> rank;
  vector<int> sz;
  DisjointSets(int n, bool Rank = true) {
    this->n = n;
    parent.resize(n + 1, 0);
    iota(parent.begin(), parent.end(), 0);
    (Rank ? rank.resize(n + 1, 1) : sz.resize(n + 1, 1));
  }
  int find(int i) {
    if (i != parent[i]) parent[i] = find(parent[i]);
    return parent[i];
  }
  void UnionByRank(int i, int j) {
    i = find(i);
    j = find(j);
    if (i == j) return;
    if (rank[i] < rank[j]) swap(i, j);
    parent[j] = i;
    rank[i] += rank[j];
  }
  void UnionBySize(int i, int j) {
    i = find(i);
    j = find(j);
    if (i == j) return;
    if (sz[i] < sz[j]) swap(i, j);
    parent[j] = i;
    sz[i] += sz[j];
  }
};
template <typename T>
class SegmentTree {
 public:
  vector<T> t;
  int n, H;
  void init(int n) {
    this->n = n;
    t.resize(2 * n);
    this->H = sizeof(int) * 8 - __builtin_clz(n);
  }
  void build() {
    for (int i = n - 1; i > 0; i--) t[i] = t[i << 1] + t[(i << 1) | 1];
  }
  void update(int pos, T val) {
    for (t[pos += n] += val; pos > 1; pos >>= 1)
      t[pos >> 1] = t[pos] + t[pos ^ 1];
  }
  T query(int l, int r) {
    T res = 0;
    for (l += n, r += n; l < r; l >>= 1, r >>= 1) {
      if (l & 1) res += t[l++];
      if (r & 1) res += t[--r];
    }
    return res;
  }
};
bool isSubsequenceString(string x, string y) {
  int i = 0, j = 0;
  while (i < x.length() && j < y.length()) x[i] == y[j] ? i++, j++ : i++;
  return (j == y.length());
}
int dfs(int a, int b, int player) {
  if (b % a == 0) return player;
  if (dfs(b % a, a, 1 - player) == player) return player;
  if (b / a == 1) return 1 - player;
  return dfs(b % a + a, b, 1 - player);
}
long long int mul(long long int a, long long int b, long long int mod) {
  return (a * b) % mod;
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  cout.tie(NULL);
  const int mod = 998244353;
  long long int n;
  cin >> n;
  vector<long long int> fact(n + 1);
  vector<long long int> invfact(n + 1);
  fact[0] = 1;
  for (long long int i = 1; i <= n; i++) fact[i] = (fact[i - 1] * i) % mod;
  invfact[n] = 1;
  for (long long int i = 2; i <= n; i++) invfact[n] = (invfact[n] * i) % mod;
  invfact[n] = binpow(invfact[n], mod - 2, mod);
  for (long long int i = n - 1; i >= 1; i--)
    invfact[i] = ((i + 1) * invfact[i + 1]) % mod;
  long long int ans = 0;
  ans = mul(n, fact[n], mod);
  for (int i = 1; i < n; i++) {
    ans = (ans + (mod - (fact[n] * invfact[i]) % mod) % mod) % mod;
  }
  cout << ans << "\n";
}