Consider an array $$$a$$$ of length $$$n$$$ with elements numbered from $$$1$$$ to $$$n$$$. It is possible to remove the $$$i$$$-th element of $$$a$$$ if $$$gcd(a_i, i) = 1$$$, where $$$gcd$$$ denotes the greatest common divisor. After an element is removed, the elements to the right are shifted to the left by one position.An array $$$b$$$ with $$$n$$$ integers such that $$$1 \le b_i \le n - i + 1$$$ is a removal sequence for the array $$$a$$$ if it is possible to remove all elements of $$$a$$$, if you remove the $$$b_1$$$-th element, then the $$$b_2$$$-th, ..., then the $$$b_n$$$-th element. For example, let $$$a = [42, 314]$$$:  $$$[1, 1]$$$ is a removal sequence: when you remove the $$$1$$$-st element of the array, the condition $$$gcd(42, 1) = 1$$$ holds, and the array becomes $$$[314]$$$; when you remove the $$$1$$$-st element again, the condition $$$gcd(314, 1) = 1$$$ holds, and the array becomes empty.  $$$[2, 1]$$$ is not a removal sequence: when you try to remove the $$$2$$$-nd element, the condition $$$gcd(314, 2) = 1$$$ is false. An array is ambiguous if it has at least two removal sequences. For example, the array $$$[1, 2, 5]$$$ is ambiguous: it has removal sequences $$$[3, 1, 1]$$$ and $$$[1, 2, 1]$$$. The array $$$[42, 314]$$$ is not ambiguous: the only removal sequence it has is $$$[1, 1]$$$.You are given two integers $$$n$$$ and $$$m$$$. You have to calculate the number of ambiguous arrays $$$a$$$ such that the length of $$$a$$$ is from $$$1$$$ to $$$n$$$ and each $$$a_i$$$ is an integer from $$$1$$$ to $$$m$$$.

The only line of the input contains two integers $$$n$$$ and $$$m$$$ ($$$2 \le n \le 3 \cdot 10^5$$$; $$$1 \le m \le 10^{12}$$$).

Print one integer — the number of ambiguous arrays $$$a$$$ such that the length of $$$a$$$ is from $$$1$$$ to $$$n$$$ and each $$$a_i$$$ is an integer from $$$1$$$ to $$$m$$$. Since the answer can be very large, print it modulo $$$998244353$$$.

#include <iostream>
using namespace std;
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <cstring>
#include <string>
#include <queue>
#include <stack>
#include <list>
#include <math.h>
#define autoin freopen("in.txt", "r", stdin)
#define fastin                       \
    {                                \
        ios::sync_with_stdio(false); \
        cin.tie(0);                  \
    }
#define MAX 300005
#define MOD 998244353
#define for1(i, n, m) for (int i = n; i < m; i++)
#define rfor(i, n, m) for (int i = n; i >= m; i--)
#define lowerbit(i) i & -i
typedef long long ll;
bool isprm(ll n)
{
    for (int i = 2; i * i <= n; ++i)
    {
        if (n % i == 0)
            return 0;

    }
    return 1;
}
// ll cc(ll a, ll b) {
//     ll d = 0;
//     while (b) {
//         if (b & 1)d = (d + a) % MOD;
//         b >>= 1;
//         a = (a + a) % MOD;
//     }
//     return d;
// }
ll fp(ll a, ll b) {
    ll d = 1;
    a = a % MOD;
    while (b) {
        if (b & 1)d = d * a % MOD;
        b >>= 1;
        a = a * a % MOD;
    }
    return d;
}

int main()
{
    ll n, m;
    cin >> n >> m;
    ll ans = m % MOD, sum = 1, cnt = 0;
    for (ll i = 2; i <= n; i++) {
        if (sum > m) {
            cnt = (cnt + fp(m, i)) % MOD;
            continue;
        }
        if (isprm(i))sum = sum * i;
        if (sum > m) {
            cnt = (cnt + fp(m, i)) % MOD;
            continue;
        }
        ans = ans * ((m / sum) % MOD) % MOD;
        // cout << fp(m, i) << '\n';
        ll o = (fp(m, i) - ans + MOD) % MOD;
        cnt = (cnt + o) % MOD;
    }
    cout << cnt << '\n';

    return 0;
}

#include <bits/stdc++.h>
using namespace std;

#define Gene template< class
#define Rics printer& operator,
Gene c> struct rge{c b, e;};
Gene c> rge<c> range(c i, c j){ return {i, j};}
struct printer{
    ~printer(){cerr<<endl;}
    Gene c >Rics(c x){ cerr<<boolalpha<<x; return *this;}
    Rics(string x){cerr<<x;return *this;}
    Gene c, class d >Rics(pair<c, d> x){ return *this,"(",x.first,", ",x.second,")";}
    Gene ... d, Gene ...> class c >Rics(c<d...> x){ return *this, range(begin(x), end(x));}
    Gene c >Rics(rge<c> x){
        *this,"["; for(auto it = x.b; it != x.e; ++it)
            *this,(it==x.b?"":", "),*it; return *this,"]";}
};
#define debug() cerr<<"LINE "<<__LINE__<<" >> ", printer()
#define dbg(x) "[",#x,": ",(x),"] "
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
int my_rand(int l, int r) {
    return uniform_int_distribution<int>(l, r) (rng);
}

#define all(v) v.begin(),v.end()
#define rall(v) v.rbegin(),v.rend()
#define pb push_back
#define ff first
#define ss second
#define ok cerr<<"Line "<<__LINE__<<" : "<<"ok"<<endl
#define DBG(a) cerr<< "Line "<<__LINE__ <<" : "<< #a <<" = "<<(a)<<endl
#define fastio {ios_base::sync_with_stdio(false);cin.tie(NULL);}

typedef long long ll;
typedef pair<int,int> pii;

const int N = 100009;
const ll MOD = 998244353;

struct mi { // WARNING: needs some adjustment to work with FFT
    int v; explicit operator int() const { return v; }
    mi():v(0) {}
    mi(ll _v):v(int(_v%MOD)) { v += (v<0)*MOD; }
};
mi& operator+=(mi& a, mi b) {
    if ((a.v += b.v) >= MOD) a.v -= MOD;
    return a; }
mi& operator-=(mi& a, mi b) {
    if ((a.v -= b.v) < 0) a.v += MOD;
    return a; }
mi operator+(mi a, mi b) { return a += b; }
mi operator-(mi a, mi b) { return a -= b; }
mi operator*(mi a, mi b) { return mi((ll)a.v*b.v); }
mi& operator*=(mi& a, mi b) { return a = a*b; }
mi pow(mi a, ll p) { assert(p >= 0); // won't work for negative p
    return p==0?1:pow(a*a,p/2)*(p&1?a:1); }
mi inv(mi a) { assert(a.v != 0); return pow(a,MOD-2); }
mi operator/(mi a, mi b) { return a*inv(b); }
bool operator==(mi a, mi b) { return a.v == b.v; }

bool isprime(ll n)
{
    for(ll i = 2; i * i <= n; i++){
        if(n % i == 0) return 0;
    }
    return 1;
}
int main()
{
    ll n, m;
    scanf("%lld %lld",&n,&m);

    mi ans = 0, total = m, bad = m, M = m;
    ll gun = 1;
    for(ll i = 2; i <= n; i++){
        total *= M;
        if(gun > m){
            ans = (ans + total);
            continue;
        }

        if(isprime(i)) gun = gun * i;

        bad *=  (m / gun) % MOD;

        mi a = total - bad;
        ans += a;
    }

    cout << ans.v << '\n';
    return 0;
}

//Khoda Hast :)//
#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define ret(x) return cout << x << endl, 0;
#define all(x) x.begin(),x.end()
#define ll long long
#define lb lower_bound
#define ub upper_bound
#define pf push_front
#define ff pop_front
#define pb push_back
#define bb pop_back
#define F first
#define S second
using namespace std;
const int N = 3e5 + 10, M = 998244353;
bool is[N];
int main()
{
    ios;
    long long n, m;
    cin >> n >> m;
    long long a = 1, mn = m % M, mx = m % M, ans = 0;
    for(long long i = 2; i <= n; i++)
    {
        if(!is[i])
        {
            for(long long j = i * i; j <= n; j += i)
                is[j] = 1;
            if(a <= m)
                a *= i;
        }
        mx *= (m % M), mx %= M;
        mn *= (m / a % M), mn %= M;
        ans += (mx - mn + M) % M, ans %= M;
    }
    cout << ans << endl;
    return 0;
}

#include <bits/stdc++.h>

using namespace std;

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"

#ifndef ATCODER_MODINT_HPP
#define ATCODER_MODINT_HPP 1

#include <cassert>
#include <numeric>
#include <type_traits>

#ifdef _MSC_VER
#include <intrin.h>
#endif

#ifndef ATCODER_INTERNAL_MATH_HPP
#define ATCODER_INTERNAL_MATH_HPP 1

#include <utility>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

// @param m `1 <= m`
// @return x mod m
constexpr long long safe_mod(long long x, long long m) {
  x %= m;
  if (x < 0) x += m;
  return x;
}

// Fast modular multiplication by barrett reduction
// Reference: https://en.wikipedia.org/wiki/Barrett_reduction
// NOTE: reconsider after Ice Lake
struct barrett {
  unsigned int _m;
  unsigned long long im;

  // @param m `1 <= m < 2^31`
  explicit barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}

  // @return m
  unsigned int umod() const { return _m; }

  // @param a `0 <= a < m`
  // @param b `0 <= b < m`
  // @return `a * b % m`
  unsigned int mul(unsigned int a, unsigned int b) const {
    // [1] m = 1
    // a = b = im = 0, so okay

    // [2] m >= 2
    // im = ceil(2^64 / m)
    // -> im * m = 2^64 + r (0 <= r < m)
    // let z = a*b = c*m + d (0 <= c, d < m)
    // a*b * im = (c*m + d) * im = c*(im*m) + d*im = c*2^64 + c*r + d*im
    // c*r + d*im < m * m + m * im < m * m + 2^64 + m <= 2^64 + m * (m + 1) < 2^64 * 2
    // ((ab * im) >> 64) == c or c + 1
    unsigned long long z = a;
    z *= b;
#ifdef _MSC_VER
    unsigned long long x;
    _umul128(z, im, &x);
#else
    unsigned long long x =
        (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
    unsigned int v = (unsigned int)(z - x * _m);
    if (_m <= v) v += _m;
    return v;
  }
};

// @param n `0 <= n`
// @param m `1 <= m`
// @return `(x ** n) % m`
constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
  if (m == 1) return 0;
  unsigned int _m = (unsigned int)(m);
  unsigned long long r = 1;
  unsigned long long y = safe_mod(x, m);
  while (n) {
    if (n & 1) r = (r * y) % _m;
    y = (y * y) % _m;
    n >>= 1;
  }
  return r;
}

// Reference:
// M. Forisek and J. Jancina,
// Fast Primality Testing for Integers That Fit into a Machine Word
// @param n `0 <= n`
constexpr bool is_prime_constexpr(int n) {
  if (n <= 1) return false;
  if (n == 2 || n == 7 || n == 61) return true;
  if (n % 2 == 0) return false;
  long long d = n - 1;
  while (d % 2 == 0) d /= 2;
  constexpr long long bases[3] = {2, 7, 61};
  for (long long a : bases) {
    long long t = d;
    long long y = pow_mod_constexpr(a, t, n);
    while (t != n - 1 && y != 1 && y != n - 1) {
      y = y * y % n;
      t <<= 1;
    }
    if (y != n - 1 && t % 2 == 0) {
      return false;
    }
  }
  return true;
}
template <int n>
constexpr bool is_prime = is_prime_constexpr(n);

// @param b `1 <= b`
// @return pair(g, x) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/g
constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
  a = safe_mod(a, b);
  if (a == 0) return {b, 0};

  // Contracts:
  // [1] s - m0 * a = 0 (mod b)
  // [2] t - m1 * a = 0 (mod b)
  // [3] s * |m1| + t * |m0| <= b
  long long s = b, t = a;
  long long m0 = 0, m1 = 1;

  while (t) {
    long long u = s / t;
    s -= t * u;
    m0 -= m1 * u;  // |m1 * u| <= |m1| * s <= b

    // [3]:
    // (s - t * u) * |m1| + t * |m0 - m1 * u|
    // <= s * |m1| - t * u * |m1| + t * (|m0| + |m1| * u)
    // = s * |m1| + t * |m0| <= b

    auto tmp = s;
    s = t;
    t = tmp;
    tmp = m0;
    m0 = m1;
    m1 = tmp;
  }
  // by [3]: |m0| <= b/g
  // by g != b: |m0| < b/g
  if (m0 < 0) m0 += b / s;
  return {s, m0};
}

// Compile time primitive root
// @param m must be prime
// @return primitive root (and minimum in now)
constexpr int primitive_root_constexpr(int m) {
  if (m == 2) return 1;
  if (m == 167772161) return 3;
  if (m == 469762049) return 3;
  if (m == 754974721) return 11;
  if (m == 998244353) return 3;
  int divs[20] = {};
  divs[0] = 2;
  int cnt = 1;
  int x = (m - 1) / 2;
  while (x % 2 == 0) x /= 2;
  for (int i = 3; (long long)(i)*i <= x; i += 2) {
    if (x % i == 0) {
      divs[cnt++] = i;
      while (x % i == 0) {
        x /= i;
      }
    }
  }
  if (x > 1) {
    divs[cnt++] = x;
  }
  for (int g = 2;; g++) {
    bool ok = true;
    for (int i = 0; i < cnt; i++) {
      if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
        ok = false;
        break;
      }
    }
    if (ok) return g;
  }
}
template <int m>
constexpr int primitive_root = primitive_root_constexpr(m);

// @param n `n < 2^32`
// @param m `1 <= m < 2^32`
// @return sum_{i=0}^{n-1} floor((ai + b) / m) (mod 2^64)
unsigned long long floor_sum_unsigned(unsigned long long n,
                                      unsigned long long m,
                                      unsigned long long a,
                                      unsigned long long b) {
  unsigned long long ans = 0;
  while (true) {
    if (a >= m) {
      ans += n * (n - 1) / 2 * (a / m);
      a %= m;
    }
    if (b >= m) {
      ans += n * (b / m);
      b %= m;
    }

    unsigned long long y_max = a * n + b;
    if (y_max < m) break;
    // y_max < m * (n + 1)
    // floor(y_max / m) <= n
    n = (unsigned long long)(y_max / m);
    b = (unsigned long long)(y_max % m);
    std::swap(m, a);
  }
  return ans;
}

}  // namespace internal

}  // namespace atcoder

#endif  // ATCODER_INTERNAL_MATH_HPP

#ifndef ATCODER_INTERNAL_TYPE_TRAITS_HPP
#define ATCODER_INTERNAL_TYPE_TRAITS_HPP 1

#include <cassert>
#include <numeric>
#include <type_traits>

namespace atcoder {

namespace internal {

#ifndef _MSC_VER
template <class T>
using is_signed_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value ||
                                  std::is_same<T, __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int128 =
    typename std::conditional<std::is_same<T, __uint128_t>::value ||
                                  std::is_same<T, unsigned __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using make_unsigned_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value,
                              __uint128_t,
                              unsigned __int128>;

template <class T>
using is_integral = typename std::conditional<std::is_integral<T>::value ||
                                                  is_signed_int128<T>::value ||
                                                  is_unsigned_int128<T>::value,
                                              std::true_type,
                                              std::false_type>::type;

template <class T>
using is_signed_int = typename std::conditional<(is_integral<T>::value &&
                                                 std::is_signed<T>::value) ||
                                                    is_signed_int128<T>::value,
                                                std::true_type,
                                                std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<(is_integral<T>::value &&
                               std::is_unsigned<T>::value) ||
                                  is_unsigned_int128<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<
    is_signed_int128<T>::value,
    make_unsigned_int128<T>,
    typename std::conditional<std::is_signed<T>::value,
                              std::make_unsigned<T>,
                              std::common_type<T>>::type>::type;

#else

template <class T>
using is_integral = typename std::is_integral<T>;

template <class T>
using is_signed_int =
    typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<is_integral<T>::value &&
                                  std::is_unsigned<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<is_signed_int<T>::value,
                                              std::make_unsigned<T>,
                                              std::common_type<T>>::type;

#endif

template <class T>
using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;

template <class T>
using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;

template <class T>
using to_unsigned_t = typename to_unsigned<T>::type;

}  // namespace internal

}  // namespace atcoder

#endif  // ATCODER_INTERNAL_TYPE_TRAITS_HPP

namespace atcoder {

namespace internal {

struct modint_base {};
struct static_modint_base : modint_base {};

template <class T>
using is_modint = std::is_base_of<modint_base, T>;
template <class T>
using is_modint_t = std::enable_if_t<is_modint<T>::value>;

}  // namespace internal

template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
struct static_modint : internal::static_modint_base {
  using mint = static_modint;

 public:
  static constexpr int mod() { return m; }
  static mint raw(int v) {
    mint x;
    x._v = v;
    return x;
  }

  static_modint() : _v(0) {}
  template <class T, internal::is_signed_int_t<T>* = nullptr>
  static_modint(T v) {
    long long x = (long long)(v % (long long)(umod()));
    if (x < 0) x += umod();
    _v = (unsigned int)(x);
  }
  template <class T, internal::is_unsigned_int_t<T>* = nullptr>
  static_modint(T v) {
    _v = (unsigned int)(v % umod());
  }

  unsigned int val() const { return _v; }

  mint& operator++() {
    _v++;
    if (_v == umod()) _v = 0;
    return *this;
  }
  mint& operator--() {
    if (_v == 0) _v = umod();
    _v--;
    return *this;
  }
  mint operator++(int) {
    mint result = *this;
    ++*this;
    return result;
  }
  mint operator--(int) {
    mint result = *this;
    --*this;
    return result;
  }

  mint& operator+=(const mint& rhs) {
    _v += rhs._v;
    if (_v >= umod()) _v -= umod();
    return *this;
  }
  mint& operator-=(const mint& rhs) {
    _v -= rhs._v;
    if (_v >= umod()) _v += umod();
    return *this;
  }
  mint& operator*=(const mint& rhs) {
    unsigned long long z = _v;
    z *= rhs._v;
    _v = (unsigned int)(z % umod());
    return *this;
  }
  mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

  mint operator+() const { return *this; }
  mint operator-() const { return mint() - *this; }

  mint pow(long long n) const {
    assert(0 <= n);
    mint x = *this, r = 1;
    while (n) {
      if (n & 1) r *= x;
      x *= x;
      n >>= 1;
    }
    return r;
  }
  mint inv() const {
    if (prime) {
      assert(_v);
      return pow(umod() - 2);
    } else {
      auto eg = internal::inv_gcd(_v, m);
      assert(eg.first == 1);
      return eg.second;
    }
  }

  friend mint operator+(const mint& lhs, const mint& rhs) {
    return mint(lhs) += rhs;
  }
  friend mint operator-(const mint& lhs, const mint& rhs) {
    return mint(lhs) -= rhs;
  }
  friend mint operator*(const mint& lhs, const mint& rhs) {
    return mint(lhs) *= rhs;
  }
  friend mint operator/(const mint& lhs, const mint& rhs) {
    return mint(lhs) /= rhs;
  }
  friend bool operator==(const mint& lhs, const mint& rhs) {
    return lhs._v == rhs._v;
  }
  friend bool operator!=(const mint& lhs, const mint& rhs) {
    return lhs._v != rhs._v;
  }

 private:
  unsigned int _v;
  static constexpr unsigned int umod() { return m; }
  static constexpr bool prime = internal::is_prime<m>;
};

template <int id>
struct dynamic_modint : internal::modint_base {
  using mint = dynamic_modint;

 public:
  static int mod() { return (int)(bt.umod()); }
  static void set_mod(int m) {
    assert(1 <= m);
    bt = internal::barrett(m);
  }
  static mint raw(int v) {
    mint x;
    x._v = v;
    return x;
  }

  dynamic_modint() : _v(0) {}
  template <class T, internal::is_signed_int_t<T>* = nullptr>
  dynamic_modint(T v) {
    long long x = (long long)(v % (long long)(mod()));
    if (x < 0) x += mod();
    _v = (unsigned int)(x);
  }
  template <class T, internal::is_unsigned_int_t<T>* = nullptr>
  dynamic_modint(T v) {
    _v = (unsigned int)(v % mod());
  }

  unsigned int val() const { return _v; }

  mint& operator++() {
    _v++;
    if (_v == umod()) _v = 0;
    return *this;
  }
  mint& operator--() {
    if (_v == 0) _v = umod();
    _v--;
    return *this;
  }
  mint operator++(int) {
    mint result = *this;
    ++*this;
    return result;
  }
  mint operator--(int) {
    mint result = *this;
    --*this;
    return result;
  }

  mint& operator+=(const mint& rhs) {
    _v += rhs._v;
    if (_v >= umod()) _v -= umod();
    return *this;
  }
  mint& operator-=(const mint& rhs) {
    _v += mod() - rhs._v;
    if (_v >= umod()) _v -= umod();
    return *this;
  }
  mint& operator*=(const mint& rhs) {
    _v = bt.mul(_v, rhs._v);
    return *this;
  }
  mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

  mint operator+() const { return *this; }
  mint operator-() const { return mint() - *this; }

  mint pow(long long n) const {
    assert(0 <= n);
    mint x = *this, r = 1;
    while (n) {
      if (n & 1) r *= x;
      x *= x;
      n >>= 1;
    }
    return r;
  }
  mint inv() const {
    auto eg = internal::inv_gcd(_v, mod());
    assert(eg.first == 1);
    return eg.second;
  }

  friend mint operator+(const mint& lhs, const mint& rhs) {
    return mint(lhs) += rhs;
  }
  friend mint operator-(const mint& lhs, const mint& rhs) {
    return mint(lhs) -= rhs;
  }
  friend mint operator*(const mint& lhs, const mint& rhs) {
    return mint(lhs) *= rhs;
  }
  friend mint operator/(const mint& lhs, const mint& rhs) {
    return mint(lhs) /= rhs;
  }
  friend bool operator==(const mint& lhs, const mint& rhs) {
    return lhs._v == rhs._v;
  }
  friend bool operator!=(const mint& lhs, const mint& rhs) {
    return lhs._v != rhs._v;
  }

 private:
  unsigned int _v;
  static internal::barrett bt;
  static unsigned int umod() { return bt.umod(); }
};
template <int id>
internal::barrett dynamic_modint<id>::bt(998244353);

using modint998244353 = static_modint<998244353>;
using modint1000000007 = static_modint<1000000007>;
using modint = dynamic_modint<-1>;

namespace internal {

template <class T>
using is_static_modint = std::is_base_of<internal::static_modint_base, T>;

template <class T>
using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;

template <class>
struct is_dynamic_modint : public std::false_type {};
template <int id>
struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};

template <class T>
using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;

}  // namespace internal

}  // namespace atcoder

#endif  // ATCODER_MODINT_HPP

#ifndef ATCODER_INTERNAL_BITOP_HPP
#define ATCODER_INTERNAL_BITOP_HPP 1

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

// @param n `0 <= n`
// @return minimum non-negative `x` s.t. `n <= 2**x`
int ceil_pow2(int n) {
  int x = 0;
  while ((1U << x) < (unsigned int)(n)) x++;
  return x;
}

// @param n `1 <= n`
// @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`
constexpr int bsf_constexpr(unsigned int n) {
  int x = 0;
  while (!(n & (1 << x))) x++;
  return x;
}

// @param n `1 <= n`
// @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`
int bsf(unsigned int n) {
#ifdef _MSC_VER
  unsigned long index;
  _BitScanForward(&index, n);
  return index;
#else
  return __builtin_ctz(n);
#endif
}

}  // namespace internal

}  // namespace atcoder

#endif  // ATCODER_INTERNAL_BITOP_HPP

#ifndef ATCODER_SEGTREE_HPP
#define ATCODER_SEGTREE_HPP 1

namespace atcoder {

template <class S, S (*op)(S, S), S (*e)()>
struct segtree {
 public:
  segtree() : segtree(0) {}
  explicit segtree(int n) : segtree(std::vector<S>(n, e())) {}
  explicit segtree(const std::vector<S>& v) : _n(int(v.size())) {
    log = internal::ceil_pow2(_n);
    size = 1 << log;
    d = std::vector<S>(2 * size, e());
    for (int i = 0; i < _n; i++) d[size + i] = v[i];
    for (int i = size - 1; i >= 1; i--) {
      update(i);
    }
  }

  void set(int p, S x) {
    assert(0 <= p && p < _n);
    p += size;
    d[p] = x;
    for (int i = 1; i <= log; i++) update(p >> i);
  }

  S get(int p) const {
    assert(0 <= p && p < _n);
    return d[p + size];
  }

  S prod(int l, int r) const {
    assert(0 <= l && l <= r && r <= _n);
    S sml = e(), smr = e();
    l += size;
    r += size;

    while (l < r) {
      if (l & 1) sml = op(sml, d[l++]);
      if (r & 1) smr = op(d[--r], smr);
      l >>= 1;
      r >>= 1;
    }
    return op(sml, smr);
  }

  S all_prod() const { return d[1]; }

  template <bool (*f)(S)>
  int max_right(int l) const {
    return max_right(l, [](S x) { return f(x); });
  }
  template <class F>
  int max_right(int l, F f) const {
    assert(0 <= l && l <= _n);
    assert(f(e()));
    if (l == _n) return _n;
    l += size;
    S sm = e();
    do {
      while (l % 2 == 0) l >>= 1;
      if (!f(op(sm, d[l]))) {
        while (l < size) {
          l = (2 * l);
          if (f(op(sm, d[l]))) {
            sm = op(sm, d[l]);
            l++;
          }
        }
        return l - size;
      }
      sm = op(sm, d[l]);
      l++;
    } while ((l & -l) != l);
    return _n;
  }

  template <bool (*f)(S)>
  int min_left(int r) const {
    return min_left(r, [](S x) { return f(x); });
  }
  template <class F>
  int min_left(int r, F f) const {
    assert(0 <= r && r <= _n);
    assert(f(e()));
    if (r == 0) return 0;
    r += size;
    S sm = e();
    do {
      r--;
      while (r > 1 && (r % 2)) r >>= 1;
      if (!f(op(d[r], sm))) {
        while (r < size) {
          r = (2 * r + 1);
          if (f(op(d[r], sm))) {
            sm = op(d[r], sm);
            r--;
          }
        }
        return r + 1 - size;
      }
      sm = op(d[r], sm);
    } while ((r & -r) != r);
    return 0;
  }

 private:
  int _n, size, log;
  std::vector<S> d;

  void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
};

}  // namespace atcoder

#endif  // ATCODER_SEGTREE_HPP

#ifndef ATCODER_LAZYSEGTREE_HPP
#define ATCODER_LAZYSEGTREE_HPP 1

#include <algorithm>
#include <cassert>
#include <iostream>
#include <vector>

namespace atcoder {

template <class S,
          S (*op)(S, S),
          S (*e)(),
          class F,
          S (*mapping)(F, S),
          F (*composition)(F, F),
          F (*id)()>
struct lazy_segtree {
 public:
  lazy_segtree() : lazy_segtree(0) {}
  explicit lazy_segtree(int n) : lazy_segtree(std::vector<S>(n, e())) {}
  explicit lazy_segtree(const std::vector<S>& v) : _n(int(v.size())) {
    log = internal::ceil_pow2(_n);
    size = 1 << log;
    d = std::vector<S>(2 * size, e());
    lz = std::vector<F>(size, id());
    for (int i = 0; i < _n; i++) d[size + i] = v[i];
    for (int i = size - 1; i >= 1; i--) {
      update(i);
    }
  }

  void set(int p, S x) {
    assert(0 <= p && p < _n);
    p += size;
    for (int i = log; i >= 1; i--) push(p >> i);
    d[p] = x;
    for (int i = 1; i <= log; i++) update(p >> i);
  }

  S get(int p) {
    assert(0 <= p && p < _n);
    p += size;
    for (int i = log; i >= 1; i--) push(p >> i);
    return d[p];
  }

  S prod(int l, int r) {
    assert(0 <= l && l <= r && r <= _n);
    if (l == r) return e();

    l += size;
    r += size;

    for (int i = log; i >= 1; i--) {
      if (((l >> i) << i) != l) push(l >> i);
      if (((r >> i) << i) != r) push((r - 1) >> i);
    }

    S sml = e(), smr = e();
    while (l < r) {
      if (l & 1) sml = op(sml, d[l++]);
      if (r & 1) smr = op(d[--r], smr);
      l >>= 1;
      r >>= 1;
    }

    return op(sml, smr);
  }

  S all_prod() { return d[1]; }

  void apply(int p, F f) {
    assert(0 <= p && p < _n);
    p += size;
    for (int i = log; i >= 1; i--) push(p >> i);
    d[p] = mapping(f, d[p]);
    for (int i = 1; i <= log; i++) update(p >> i);
  }
  void apply(int l, int r, F f) {
    assert(0 <= l && l <= r && r <= _n);
    if (l == r) return;

    l += size;
    r += size;

    for (int i = log; i >= 1; i--) {
      if (((l >> i) << i) != l) push(l >> i);
      if (((r >> i) << i) != r) push((r - 1) >> i);
    }

    {
      int l2 = l, r2 = r;
      while (l < r) {
        if (l & 1) all_apply(l++, f);
        if (r & 1) all_apply(--r, f);
        l >>= 1;
        r >>= 1;
      }
      l = l2;
      r = r2;
    }

    for (int i = 1; i <= log; i++) {
      if (((l >> i) << i) != l) update(l >> i);
      if (((r >> i) << i) != r) update((r - 1) >> i);
    }
  }

  template <bool (*g)(S)>
  int max_right(int l) {
    return max_right(l, [](S x) { return g(x); });
  }
  template <class G>
  int max_right(int l, G g) {
    assert(0 <= l && l <= _n);
    assert(g(e()));
    if (l == _n) return _n;
    l += size;
    for (int i = log; i >= 1; i--) push(l >> i);
    S sm = e();
    do {
      while (l % 2 == 0) l >>= 1;
      if (!g(op(sm, d[l]))) {
        while (l < size) {
          push(l);
          l = (2 * l);
          if (g(op(sm, d[l]))) {
            sm = op(sm, d[l]);
            l++;
          }
        }
        return l - size;
      }
      sm = op(sm, d[l]);
      l++;
    } while ((l & -l) != l);
    return _n;
  }

  template <bool (*g)(S)>
  int min_left(int r) {
    return min_left(r, [](S x) { return g(x); });
  }
  template <class G>
  int min_left(int r, G g) {
    assert(0 <= r && r <= _n);
    assert(g(e()));
    if (r == 0) return 0;
    r += size;
    for (int i = log; i >= 1; i--) push((r - 1) >> i);
    S sm = e();
    do {
      r--;
      while (r > 1 && (r % 2)) r >>= 1;
      if (!g(op(d[r], sm))) {
        while (r < size) {
          push(r);
          r = (2 * r + 1);
          if (g(op(d[r], sm))) {
            sm = op(d[r], sm);
            r--;
          }
        }
        return r + 1 - size;
      }
      sm = op(d[r], sm);
    } while ((r & -r) != r);
    return 0;
  }

 private:
  int _n, size, log;
  std::vector<S> d;
  std::vector<F> lz;

  void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
  void all_apply(int k, F f) {
    d[k] = mapping(f, d[k]);
    if (k < size) lz[k] = composition(f, lz[k]);
  }
  void push(int k) {
    all_apply(2 * k, lz[k]);
    all_apply(2 * k + 1, lz[k]);
    lz[k] = id();
  }
};

}  // namespace atcoder

#endif  // ATCODER_LAZYSEGTREE_HPP

ostream& operator<<(ostream& os, atcoder::modint1000000007& x) { return os << x.val(); }
ostream& operator<<(ostream& os, atcoder::modint998244353& x) { return os << x.val(); }

template <typename A, typename B>
ostream& operator<<(ostream& os, const pair<A, B>& p) { return os << '(' << p.first << ", " << p.second << ')'; }
void print() { cout << endl; }
template <typename T, typename... Tail>
void print(T&& seq, Tail... tail) {
  if constexpr (ranges::range<T> && !convertible_to<T, string>)
    for (const auto& x : seq) cout << x << ' ';
  else
    cout << seq;
  cout << ' ';
  print(tail...);
}

#pragma GCC diagnostic pop

using S = int;
S op(S l, S r) { return l + r; }
S e() { return 0; }
// atcoder::segtree<S, op, e> segTree(vector<S>(N, e()));
// atcoder::lazy_segtree<S, op, e, F, mapping, composition, id> segTree(vector<S>(N, e()));

using modint = atcoder::modint998244353;

vector<int> smallestPrimeFactor;
void initPrimes(int n) {
  smallestPrimeFactor.assign(n, -1);
  for (int64_t i = 2; i < n; i++) {
    if (smallestPrimeFactor[i] == -1) {
      smallestPrimeFactor[i] = i;
      for (int64_t j = i * i; j < n; j += i) {
        if (smallestPrimeFactor[j] == -1) {
          smallestPrimeFactor[j] = i;
        }
      }
    }
  }
}

bool isPrime(int n) {
  assert(n < ssize(smallestPrimeFactor));
  return smallestPrimeFactor[n] == n;
}

map<int, int> primeFactors(int n) {
  map<int, int> freq;
  while (n != 1) {
    int x = smallestPrimeFactor[n];
    n /= x;
    freq[x] += 1;
  }
  return freq;
}
void solve() {
  int64_t N, M;
  cin >> N >> M;

  int64_t INF = 1e18;
  vector<int64_t> pref(N + 1, INF);
  pref[0] = 1;
  for (int i = 1; i <= N; i++) {
    int64_t extra = 1;
    if (i == 1 || isPrime(i)) {
      extra = i;
    }
    pref[i] = pref[i - 1] * extra;
    if (pref[i] > M) {
      break;
    }
  }

  vector<int64_t> ways(N + 1, INF);
  ways[0] = 0;

  modint n = N;
  modint m = M;
  modint ans;
  if (M == 1) {
    ans = N;
  } else {
    ans = ((m.pow(N + 1) - 1) / (m - 1)) - 1;
  }
  modint cum = 1;
  for (int i = 1; i <= N; i++) {
    ways[i] = M / pref[i];
    cum *= ways[i];
    ans -= cum;
  }

  print(ans);
}

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);
  cin.exceptions(ios::badbit | ios::failbit);
  cout << fixed << setprecision(15);
  initPrimes(1e6);
  int TC = 1;
  while (TC--) {
    solve();
  }

  return 0;
}

#include<bits/stdc++.h>
using namespace std;
#define int long long
template<typename G>inline void read(G&x) {G f=1;x=0;char ch=getchar();while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();if(ch=='-') f=-1,ch=getchar();while(ch>='0'&&ch<='9') x=x*10+(ch^48),ch=getchar();x*=f;}
const int MAXN=3e5+5,p=998244353;
int T,n,m,ans,mul,sum,cnt,pri[MAXN];
bool f[MAXN];
int qpow(int x,int y) {
	int res=1;
	while(y) {
		if(y&1) res=res*x%p;
		x=x*x%p,y>>=1;
	}
	return res;
}
void euler() {
	for(int i=2;i<=3e5;++i) {
		if(!f[i]) {
			pri[++cnt]=i;
		}
		for(int j=1;j<=cnt;++j) {
			if(i*pri[j]>3e5) break;
			f[i*pri[j]]=1;
			if(i%pri[j]==0) break;
		}
	}
}
int now,tot;
signed main() {
	euler();
	read(n),read(m);ans=sum=m%p,mul=1;now=tot=m%p;
	for(int i=2;i<=n;++i) {
		if(!f[i]&&mul<=m) mul*=i;
		now=(now*(m%p))%p,tot=(tot+now)%p;
		ans=(ans*((m/mul)%p))%p,sum=(sum+ans)%p;
	}
	printf("%lld\n",((tot-sum)%p+p)%p);
	return 0;
}

//
// Created by vv123 on 2022/8/29.
//
//#pragma GCC optimize(3)
#include <bits/stdc++.h>
#define int long long
using namespace std;

const int N = 2e6 + 10;
int n, m, a[N];

const int mod = 998244353;

inline int mul(int a, int b) {
    int res = 0;
    for (; b; b >>= 1) {
        if (b & 1) res = (res + a) % mod;
        a = a * 2 % mod;
    }
    return res;
}
inline int pow(int a, int b) {
    a %= mod;
    int res = 1;
    for (; b; b >>= 1) {
        if (b & 1) res = res * a % mod;
        a = a * a % mod;
    }
    return res;
}

inline bool isprime(int x) {
    for (int i = 2; i * i <= x; i++)
        if (x % i == 0) return false;
    return true;
}

int f[N];
void solve() {
    cin >> n >> m;

    int pi = 1; f[0] = 1; f[1] = m;
    for (int i = 2; i <= n; i++) {
        if (pi > 1e12) break;
        if (isprime(i) && pi <= 1e12) {
            pi *= i;
            f[i] = m / pi % mod;
        } else {
            f[i] = f[i - 1];
        }
    }

    int tot = 0;
    for (int i = 1; i <= n; i++) tot = (tot + pow(m, i)) % mod;
    int cnt = 0; pi = 1;
    for (int i = 1; i <= n; i++) {
        pi = pi * f[i] % mod;
        cnt = (cnt + pi) % mod;
    }
    cout << ((tot - cnt) % mod + mod) % mod << "\n";
}

signed main() {
    //ios::sync_with_stdio(false); cin.tie(0);
    int T = 1; //cin >> T;
    while (T--) {
        solve();
    }
    return 0;
}

#include <bits/stdc++.h>
#define INT long long
using namespace std;
const int mod = 998244353;
const int NN = 300100;
int cnt[NN], flag[NN];
int main() {
#ifndef ONLINE_JUDGE
	freopen("in.in", "r", stdin);
	freopen("out.out", "w", stdout);
#endif
	INT n, m;
	cin >> n >> m;
	INT ans = 0, p = 1;
	INT M = m%mod;
	for(int i = 1; i <= n; i ++){
		p = p*M%mod;
		ans = (ans + p)%mod;
	}
	for(int i = 2; i <= n; i ++){
		if(flag[i] == 0){
			for(int j = i + i; j <= n; j += i) flag[j] = 1;
		}
	}
	p = M;
	INT q = 1;
	INT d = M;
	for(int i = 2; i <= n; i ++){
		INT c = 0;
		if(flag[i] == 0){
			if(q*i <= m) q = q*i;
			else break;
		}
		c = m/q;
		c = c%mod;
		p = p*c%mod;
		d = (d + p)%mod;
	}
	ans = (ans + mod - d)%mod;
	cout << ans;
	return 0;
}

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <random>

using namespace std;
using namespace __gnu_pbds;

typedef long long ll;
typedef unsigned long long ull;
typedef tree<array <int, 3>, null_type, less<>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;
#define AboTaha_on_da_code ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
#define X first
#define Y second

const int dx[8]={0, 0, 1, -1, 1, -1, -1, 1}, dy[8]={1, -1, 0, 0, 1, -1, 1, -1};
const int M = 1e9+7, M2 = 998244353;
const double EPS = 1e-9;

vector <bool> isprime;
vector <ll> dp;
vector <int> pr;

ll mpow(ll a, ll b)
{
    ll res = 1;
    while(b) {
        if (b&1) res*=a, res%=M2;
        a*=a, a%=M2;
        b/=2;
    }
    return res;
}

void dracarys(int tc)
{
    ll n, m; cin >> n >> m;
    isprime.assign(n+1, true);
    for (ll i = 2; i <= n; i++) {
        if (!isprime[i]) continue;
        pr.push_back(i);
        for (ll j = i*i; j <= n; j+=i) isprime[j] = false;
    }
    ll acc = m%M2, ans = 0, cur = 1;
    for (int i = 2, j = 0; i <= n; i++) {
        while(j < pr.size() && i%pr[j] == 0) {
            if (INT64_MAX/pr[j] < cur) {
                cur = m+1;
                break;
            }
            cur*=1LL*pr[j++];
        }
        acc*=m/cur%M2, acc%=M2;
        ans+=(mpow(m%M2, i)-acc+M2)%M2, ans%=M2;
    }
    cout << ans;
}

int main()
{
    AboTaha_on_da_code

//    freopen("Ain.txt", "r", stdin);
//    freopen("Aout.txt", "w", stdout);

    int T = 1; // cin >> T;

    for (int i = 1; i <= T; i++) {
//        cout << "Case #" << i << ": ";
        dracarys(i);
        cout << '\n';
    }
    return 0;
}

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e5 + 10, mod = 998244353;
int st[N], primes[N], cnt;
int a[N], s[N], mi[N];
typedef long long ll;
void init(int n)
{
    for (int i = 2; i <= n; i++)
    {
        if (!st[i])
        {
            primes[cnt++] = i;
        }
        for (int j = 0; primes[j] * i <= n; j++)
        {
            st[primes[j] * i] = 1;
            if (i % primes[j] == 0)
                break;
        }
    }
}
int qmi(int x, int y)
{
    int res = 1;
    while (y)
    {
        if (y & 1)
            res = res * y % mod;
        y >>= 1;
        x = x * x % mod;
    }
    return res;
}
void solve()
{
    int n, m;
    cin >> n >> m;
    init(N - 1);
    a[1] = m % mod;
    mi[1] = m % mod;
    ll ans = 0, sum = 1;
    for (int i = 2; i <= n; i++)
    {
        mi[i] = ((mi[i - 1] % mod) * (m % mod)) % mod;
        // cout << mi[i] << endl;
        ans += mi[i];
        ans %= mod;
    }
    // cout << ans << endl;
    //  cout << ans << endl;
    for (int i = 2; i <= n; i++)
    {
        if (!st[i])
        {
            sum *= i;
            if (sum > m)
                break;
        }
        a[i] = (a[i - 1] % mod) * ((m / sum) % mod) % mod;
        a[i] %= mod;
        ans -= a[i];
        ans += mod;
        ans %= mod;
    }
    cout << ans;
}

signed main()
{
    int t = 1;
    while (t--)
    {
        solve();
    }
}

#include <iostream>
#include <ranges>
#include <algorithm>
#include <numeric>
#include <vector>
#include <array>
#include <set>
#include <map>
#include <bit>
#include <sstream>
#include <list>
#include <stack>

typedef long long integerType;
typedef integerType n;
typedef std::vector<n> v;
typedef std::vector<v> V;
typedef std::set<n> s;
typedef std::multiset<n> S;
typedef std::map<n, n> m;
typedef std::string r;
typedef std::vector<r> R;
typedef std::vector<bool> b;

struct RHEXAOCrocks {
	RHEXAOCrocks() { std::ios_base::sync_with_stdio(false); std::cin.tie(nullptr); }
	template<class T>
	operator T() const { T n; std::cin >> n; return n; }
	std::string operator()() { std::string s; std::cin >> s; return s; }
	v operator()(n n) { v vec(n); for (auto& n : vec) std::cin >> n; return vec; }
	R operator()(integerType n, char del) {
		R vec(n); char ch; std::cin >> ch; vec[0].push_back(ch); int c;
		for (integerType i{}; i < n;++i)
			while ((c = std::cin.get()) != del)
				vec[i].push_back(c);
		return vec;
	}
	V operator()(n r, n c) { V tab(r, v(c)); for (auto& e : tab) for (auto& n : e) std::cin >> n; return tab; }
	template<class T> RHEXAOCrocks& operator[](const T& t) { std::cout << t; return *this; }
	RHEXAOCrocks& operator[](const R& a) { for (auto& e : a) std::cout << e << '\n'; return *this; }
	template<class Ty, template<typename T, typename A = std::allocator<T>> class C> RHEXAOCrocks& operator[](const C<Ty>& c) {
		for (auto Cc{ c.begin() }; Cc != c.end(); std::cout << *Cc << " \n"[++Cc == c.end()]); return *this;
	}
	template<class Ty, template<typename T, typename A = std::allocator<T>> class C> RHEXAOCrocks& operator[](const std::vector<C<Ty>>& c) {
		for (auto& e : c) for (auto E{ e.begin() }; E != e.end(); )std::cout << *E << " \n"[++E == e.end()]; return *this;
	}
}o;

#define i(b,e, ...) for(integerType i : std::views::iota(b,e) __VA_ARGS__)
#define _i(b,e, ...) for(integerType i : std::views::iota(b,e) | std::views::reverse __VA_ARGS__)
#define j(b,e, ...) for(integerType j : std::views::iota(b,e) __VA_ARGS__)
#define _j(b,e, ...) for(integerType j : std::views::iota(b,e) | std::views::reverse __VA_ARGS__)
#define k(b,e, ...) for(integerType k : std::views::iota(b,e) __VA_ARGS__)
#define _k(b,e, ...) for(integerType k : std::views::iota(b,e) | std::views::reverse __VA_ARGS__)
#define l(b,e, ...) for(integerType l : std::views::iota(b,e) __VA_ARGS__)
#define _l(b,e, ...) for(integerType l : std::views::iota(b,e) | std::views::reverse __VA_ARGS__)

#define Aa for(auto A = a.begin(); A != a.end(); ++A)
#define Bb for(auto B = b.begin(); B != b.end(); ++B)
#define Cc for(auto C = c.begin(); C != c.end(); ++C)
#define Dd for(auto D = d.begin(); D != d.end(); ++D)

#define z(a) (n)((a).size())

using namespace std;
namespace ra = ranges;

inline void nwmn(n nw, n& mn) { mn -= ((nw) < mn) * (mn - (nw)); }
inline void nwmx(n nw, n& mx) { mx += ((nw) > mx) * ((nw)-mx); }

int main()
{
	n m{ o }, a{ o }, I{ 1 }, p{ 1 }, k{ 1 }, M{ 998244353 }, s{};
	auto f = [](n m) {
		for (n i{ 2 }; i * i <= m; ++i)
			if (!(m % i))
				return false;
		return true;
	};
	i(1, m + 1) {
		(p *= (a % M)) %= M;
		if (I <= a && f(i))
			I *= i;
		(k *= a / I % M) %= M;
		(s += p - k + M) %= M;
	}
	o[s]['\n'];
}

#include<bits/stdc++.h>

using namespace std;

#define all(x) x.begin() , x.end()
#define pii pair<int, int>
#define piii pair<int, pii>
#define pll pair<ll, ll>
#define plll pair<ll, pll>
#define sze(x)  (ll) (x.size())
#define pb push_back
#define qb pop_back
#define F first
#define S second
#define wall cerr<<"--------------------------------------"<<endl

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

typedef long long ll;
typedef double db;

const ll INF = 1e18;
const ll maxn = 4e5 + 10;
const ll mod = 998244353;

ll t , n , m , a[maxn] , b[maxn] , x , y , z , fac[maxn] , ans , prime[maxn] , val[maxn];
vector<ll> ve[maxn];
bool mark[maxn];
set<ll> se;

ll pw(ll a , ll b){
        if(b == 0)return 1;

        ll x = pw(a , b/2);

        x = (x * x)%mod;

        if(b&1)x = (x*a)%mod;

        return x;
}

int main()
{
  ios_base::sync_with_stdio(0);cin.tie(NULL);cout.tie(NULL);
  cin>>n>>m;
  mark[1] = 1;
  for(int i=2; i<=sqrt(n)+10; i++){
        if(mark[i] == 0){
                for(int j=2; j*i<=n; j++){
                        mark[j*i] = 1;
                }
        }
  }
  for(int i=0; i<=n + 10; i++){
        prime[i] = 1;
        val[i] = 1;
  }
  //wall;
  for(int i=2; i<=n; i++){
        if(prime[i-1] == -1){
                prime[i] = -1;
        }
        else{
                prime[i] = prime[i-1];
                if(mark[i] == 0){
                        prime[i] *= i;
                }
                if(prime[i] > m){
                        prime[i] = -1;
                }
        }
        //cout<<i<<" : prime = "<<prime[i]<<endl;
  }
  //wall;
  val[1] = m;
  for(int i=1; i<=n; i++){
        if(prime[i] == -1){
                val[i] = 0;
                continue;
        }
        ll x = (m / prime[i])%mod;
        val[i] = (val[i-1] * x)%mod;
        //cout<<i<<" : val[i] = "<<val[i]<<" , x = "<<(m/prime[i])<<endl;
  }
  //wall;
  ll x = m % mod;
  ll ans = mod;
  for(int i=1; i<=n; i++){
        ans = (ans+pw(x , i))%mod;
        ans = (ans - val[i])%mod;

        while(ans < 0)ans+=mod;
        //cout<<i<<" ans[i]="<<ans<<endl;
  }
  cerr<<"ans = ";
  cout<<ans;
  return 0;
}
/**
4
3
1 1 2
4
4 4 4 4
1
1
5
1 3 2 1 1
*/
/**
1
5
1 3 2 1 1
**/
/*
by
                        .         .--. .--. .--.
                      .'|         |__| |__| |__|
                     <  |         .--. .--. .--.
    __                | |         |  | |  | |  |
 .:--.'.          _   | | .'''-.  |  | |  | |  |
/ |   \ |       .' |  | |/.'''. \ |  | |  | |  |
`" __ | |      .   | /|  /    | | |  | |  | |  |
 .'.''| |    .'.'| |//| |     | | |__| |__| |__|
/ /   | |_ .'.'.-'  / | |     | |
\ \._,\ '/ .'   \_.'  | '.    | '.
 --'  "             '---'   '---

*/

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
#define Code ios_base::sync_with_stdio(false);
#define By cin.tie(NULL);
#define Asquare cout.tie(NULL);
#define maxe *max_element
#define mine *min_element
using ll= long long;
using lld= long double;
using ull= unsigned long long;
const lld pi= 3.141592653589793238;
const ll INF= LONG_LONG_MAX;
const ll mod=998244353;
typedef pair<ll, ll> pll;
typedef pair<int,int> pii;
typedef vector<ll> vll;
typedef vector<int> vi;
typedef vector<pair<int,int>> vpii;
typedef vector<pll> vpll;
typedef vector<string> vs;
typedef vector<vi> vvi;
typedef vector<vll> vvl;
typedef unordered_map<ll,ll> umll;
typedef unordered_map<int,int> umii;
typedef map<int,int> mii;
typedef map<ll,ll> mll;
#define mem0(x) memset(x,0,sizeof x)
#define mem1(x) memset(x,-1,sizeof x)
#define ff first
#define ss second
#define pb push_back
#define mp make_pair
#define f(i,n) for(int i=0;i<n;i++)
#define f1(i,n) for(int i=1;i<n;i++)
#define all(v) v.begin(),v.end()
ll const N=1e5;
template<typename T1, typename T2> // cin >> pair<T1, T2>
istream& operator>>(istream &istream, pair<T1, T2> &p) { return (istream >> p.first >> p.second); }
template<typename T> // cin >> vector<T>
istream& operator>>(istream &istream, vector<T> &v){for (auto &it : v)cin >> it;return istream;}
template<typename T1, typename T2> // cout << pair<T1, T2>
ostream& operator<<(ostream &ostream, const pair<T1, T2> &p) { return (ostream << p.first <<" "<< p.second); }
template<typename T> // cout << vector<T>
ostream& operator<<(ostream &ostream, const vector<T> &c) { for (auto &it : c) cout << it <<"  ";  return ostream; }
template <typename T>
void print(T &&t)  { cout << t << "\n"; }
void coutarr(ll arr[], ll n){f(i,n) cout << arr[i] << " ";cout << "\n";}
template<typename T>
void coutvec(vector<T>v){ll n=v.size();f(i,n)cout<<v[i]<<" ";cout<<"\n";}
template<typename T>
ll sumvec(vector<T>v){ll n=v.size();ll s=0;f(i,n)s+=v[i];return s;}
ll gcd(ll a, ll b){if (b == 0)return a;return gcd(b, a % b);}
ll lcm(ll a, ll b){return (a/gcd(a,b)*b);}
ll mM(ll a,ll b,ll mod){ll res = 0;a %= mod;while (b){if (b & 1)res = (res + a) % mod;b >>= 1;}return res;}
bool sorta(const pair<int,int> &a,const pair<int,int> &b){return (a.second < b.second);}
bool sortb(const pair<int,int> &a,const pair<int,int> &b){return (a.second > b.second);}
bool isPrime(ll n){if(n<=1)return false;if(n<=3)return true;if(n%2==0||n%3==0)return false;for(int i=5;i*i<=n;i=i+6)if(n%i==0||n%(i+2)==0)return false;return true;}
bool isPowerOfTwo(int n){if(n==0)return false;return (ceil(log2(n)) == floor(log2(n)));}
bool isPerfectSquare(ll x){if (x >= 0) {ll sr = sqrt(x);return (sr * sr == x);}return false;}
vector<int>factorize(int n){
    vector<int>res;
    for(int i=2;i*i<=n;++i){
        while(n%i==0){
            res.push_back(i);
            n/=i;
        }
    }
    if(n!=1)res.push_back(n);
    return res;
}
ll pow_mod(ll a, ll d) {
	if (a % mod == 0) return 0;
	a %= mod;
	if (d == 0) return 1LL;
	ll r = pow_mod(a, d / 2);
	r = (r * r) % mod;
	if ((d % 2) == 1)
		r = (r * a) % mod;
	return r;
}
const ll maxn=105;
ll fac[maxn],invfact[maxn];
ll power(ll x, ll y) {
    ll res=1;
    x=x%mod;
    while(y>0) {
        if(y&1)
            res=(res*x)%mod;
        y=y>>1;
        x=(x*x)%mod;
    }
    return res;
}
ll modInverse(ll n){return power(n, mod - 2);}
void comp(){
    fac[0]=1,invfact[0]=1;
    for(ll i=1;i<maxn;i++){
        fac[i]=(fac[i-1]*i)%mod;
        invfact[i]=modInverse(fac[i]);
    }
}
ll ncr(ll n, ll r, ll p=mod) {
    if(r<0||n<0)
        assert(false);
    if(n<r)return 0;
    if(r==0||r==n)
        return 1;
    return (fac[n]*invfact[r]%mod)*invfact[n-r]%mod;
}
void printDivisors(int n){
    for (int i=1;i<=sqrt(n);i++){
        if(n%i==0){
            if(n/i==i)printf("%d",i);
            else printf("%d%d",i,n/i);
        }
    }
}
ll count_bit(ll val){
    ll count=0;
    while(val)count++,val=val&(val-1);
    return count;
}
void prime_num(int R){
    vector<bool>isprime(R+1,true);
    isprime[0]=isprime[1]=false;
    for(int i=2;i*i<=R;++i){
        if(isprime[i]==true){
            for(int j=2*i;j<=R;j=j+i)isprime[j]=false;
        }
    }
}
void sol(void){
    ll n;cin>>n;ll m;cin>>m;
    ll to_remove=1;ll val=1;
    ll ans=0;
    ll count=0;
    for (ll i=1;i<=n;++i) {
        if (isPrime(i)){
            to_remove=min(to_remove*i,(ll)1e13);
        }
        (val*=m/to_remove%mod )%=mod;
        (ans+=val)%=mod;
        (count += pow_mod(m%mod,i))%=mod;
    }
    cout<<(count-ans+mod)%mod<<endl;
}
int main()
{ll t;
t=1;
// cin>>t;
f(i,t) sol();
return 0;
}

#include <bits/stdc++.h>
#include <cassert>
using namespace std;
#define ll long long
#define ull unsigned long long
#define ld long double
#define pii pair<int, int>
#define pll pair<ll, ll>
#define fr first
#define sc second
#define vt vector
#define all(c) (c).begin(), (c).end()
#define sz(x) (int)(x).size()

#define EXPAND( x ) x // Use this if MS Visual Studio doesn't expand __VA_ARGS__ correctly
#define F_OR(i, a, b, s) for (int i = (a); (s) > 0 ? i < (b) : i > (b); i += (s))
#define F_OR1(e) F_OR(i, 0, e, 1)
#define F_OR2(i, e) F_OR(i, 0, e, 1)
#define F_OR3(i, b, e) F_OR(i, b, e, 1)
#define F_OR4(i, b, e, s) F_OR(i, b, e, s)
#define GET5(a, b, c, d, e, ...) e
#define F_ORC(...) EXPAND( GET5(__VA_ARGS__, F_OR4, F_OR3, F_OR2, F_OR1) )
#define FOR(...) EXPAND( F_ORC(__VA_ARGS__ )(__VA_ARGS__) )
#define EACH(x, a) for (auto& x : a)

const double EPS = 1e-9;
const int INF = 1e9 + 7;
const int MOD = 998244353;
const int dy[] = { 0, 0, 1, -1, 1, 1, -1, -1 };
const int dx[] = { 1, -1, 0, 0, 1, -1, 1, -1 };

ll gcd(ll a, ll b) {
	if (b == 0) return a;
	else return gcd(b, a % b);
}

ll lcm(ll a, ll b) {
	return a * b / gcd(a, b);
}

const int MAX = 3e5;

bool isPrime[MAX + 1];
vector<int> prime(1, 2);

void getPrime() {
	fill(isPrime + 2, isPrime + MAX + 1, 1);

	for (ll i = 4; i <= MAX; i += 2)
		isPrime[i] = 0;
	for (ll i = 3; i <= MAX; i++) {
		if (isPrime[i]) prime.push_back(i);
		for (ll j = i * i; j <= MAX; j += i * 2)
			isPrime[j] = 0;
	}
}

ll n, m;

int main() {
	#ifndef ONLINE_JUDGE
	freopen("/Users/jeongwoo-kyung/Programming/CP-Codes/input.txt", "r", stdin);
	freopen("/Users/jeongwoo-kyung/Programming/CP-Codes/output.txt", "w", stdout);
	#endif

	cin.tie(NULL); cout.tie(NULL);
	ios_base::sync_with_stdio(false);

    getPrime();

    cin >> n >> m;

    vt<ll> non(n + 1);
    non[1] = m % MOD;

    ll lc = 1;
    for (ll i = 2; i <= n; i++) {
        if (isPrime[i] && lc <= m)
            lc = lcm(lc, i);

        ll cnt = m / lc;
        non[i] = non[i - 1] * (cnt % MOD) % MOD;
    }

    vt<ll> sum(n + 1);
    sum[1] = m % MOD;
    for (int i = 2; i <= n; i++) {
        sum[i] = sum[i - 1] * (m % MOD) % MOD;
    }

    ll ans = 0;
    for (int i = 1; i <= n; i++) {
        ans = (ans + sum[i] - non[i]) % MOD;
    }

    cout << (ans + MOD) % MOD;

	return 0;
}

/*
    Last Weapon is my own algorithms library for competitive programming, it is a fork from ACL with some alternative algorithms and additional features. Use it at your own risk.
    Repo: https://github.com/lychees/last-weapon
    Blog: https://www.shuizilong.com/house
*/
#pragma comment(linker, "/STACK:36777216")
#define LOCAL
#include <functional>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <numeric>
#include <cstring>
#include <climits>
#include <cassert>
#include <complex>
#include <cstdio>
#include <string>
#include <vector>
#include <bitset>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <list>
#include <set>
#include <map>
#include <forward_list>

using namespace std;

#define REP(i, n) for (int i=0;i<n;++i)
#define FOR(i, a, b) for (int i=a;i<b;++i)
#define DWN(i, b, a) for (int i=b-1;i>=a;--i)
#define REP_1(i, n) for (int i=1;i<=n;++i)
#define FOR_1(i, a, b) for (int i=a;i<=b;++i)
#define DWN_1(i, b, a) for (int i=b;i>=a;--i)

#define ECH(it, A) for (__typeof((A).begin()) it=(A).begin(); it != (A).end(); ++it)
#define rECH(it, A) for (__typeof((A).rbegin()) it=(A).rbegin(); it != (A).rend(); ++it)
#define REP_S(i, str) for (char*i=str;*i;++i)
#define REP_L(i, hd, suc) for (int i=hd;i;i=suc[i])
#define REP_G(i, u) REP_L(i,hd[u],suc)
#define REP_SS(x, s) for (int x=s;x;x=(x-1)&s)
#define DO(n) for ( int ____n = n; ____n-->0; )

#define ALL(A) A.begin(), A.end()
#define LLA(A) A.rbegin(), A.rend()
#define CPY(A, B) memcpy(A, B, sizeof(A))
#define INS(A, P, B) A.insert(A.begin() + P, B)
#define ERS(A, P) A.erase(A.begin() + P)
#define LBD(A, x) (lower_bound(ALL(A), x) - A.begin())
#define UBD(A, x) (upper_bound(ALL(A), x) - A.begin())
#define CTN(T, x) (T.find(x) != T.end())
#define SZ(A) int((A).size())
#define PB push_back
#define MP(A, B) make_pair(A, B)
#define PTT pair<T, T>
#define Ts *this
#define rTs return Ts
#define fi first
#define se second
#define re real()
#define im imag()

#define Rush for(int ____T=RD(); ____T--;)
#define Display(A, n, m) {                      \
  REP(i, n){		                            \
        REP(j, m-1) cout << A[i][j] << " ";     \
        cout << A[i][m-1] << endl;		        \
	}						                    \
}
#define Display_1(A, n, m) {                    \
	REP_1(i, n){		                        \
        REP_1(j, m-1) cout << A[i][j] << " ";   \
        cout << A[i][m] << endl;		        \
	}						                    \
}

typedef long long LL;
typedef double DB;
typedef unsigned uint;
typedef unsigned long long uLL;

typedef vector<int> VI;
typedef vector<char> VC;
typedef vector<string> VS;
typedef vector<LL> VL;
typedef vector<DB> VF;
typedef set<int> SI;
typedef set<string> SS;
typedef map<int, int> MII;
typedef map<string, int> MSI;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
typedef vector<PII> VII;
typedef vector<VI> VVI;
typedef vector<VII> VVII;

template<class T> inline T& RD(T &);
template<class T> inline void OT(const T &);
inline LL RD(){LL x; return RD(x);}
inline DB& RF(DB &);
inline DB RF(){DB x; return RF(x);}
inline char* RS(char *s);
inline char& RC(char &c);
inline char RC();
inline char& RC(char &c){scanf(" %c", &c); return c;}
inline char RC(){char c; return RC(c);}

template<class T0, class T1> inline T0& RD(T0 &x0, T1 &x1){RD(x0), RD(x1); return x0;}
template<class T0, class T1, class T2> inline T0& RD(T0 &x0, T1 &x1, T2 &x2){RD(x0), RD(x1), RD(x2); return x0;}
template<class T0, class T1, class T2, class T3> inline T0& RD(T0 &x0, T1 &x1, T2 &x2, T3 &x3){RD(x0), RD(x1), RD(x2), RD(x3); return x0;}
template<class T0, class T1, class T2, class T3, class T4> inline T0& RD(T0 &x0, T1 &x1, T2 &x2, T3 &x3, T4 &x4){RD(x0), RD(x1), RD(x2), RD(x3), RD(x4); return x0;}
template<class T0, class T1, class T2, class T3, class T4, class T5> inline T0& RD(T0 &x0, T1 &x1, T2 &x2, T3 &x3, T4 &x4, T5 &x5){RD(x0), RD(x1), RD(x2), RD(x3), RD(x4), RD(x5); return x0;}
template<class T0, class T1, class T2, class T3, class T4, class T5, class T6> inline T0& RD(T0 &x0, T1 &x1, T2 &x2, T3 &x3, T4 &x4, T5 &x5, T6 &x6){RD(x0), RD(x1), RD(x2), RD(x3), RD(x4), RD(x5), RD(x6); return x0;}
template<class T0, class T1> inline void OT(const T0 &x0, const T1 &x1){OT(x0), OT(x1);}
template<class T0, class T1, class T2> inline void OT(const T0 &x0, const T1 &x1, const T2 &x2){OT(x0), OT(x1), OT(x2);}
template<class T0, class T1, class T2, class T3> inline void OT(const T0 &x0, const T1 &x1, const T2 &x2, const T3 &x3){OT(x0), OT(x1), OT(x2), OT(x3);}
template<class T0, class T1, class T2, class T3, class T4> inline void OT(const T0 &x0, const T1 &x1, const T2 &x2, const T3 &x3, const T4 &x4){OT(x0), OT(x1), OT(x2), OT(x3), OT(x4);}
template<class T0, class T1, class T2, class T3, class T4, class T5> inline void OT(const T0 &x0, const T1 &x1, const T2 &x2, const T3 &x3, const T4 &x4, const T5 &x5){OT(x0), OT(x1), OT(x2), OT(x3), OT(x4), OT(x5);}
template<class T0, class T1, class T2, class T3, class T4, class T5, class T6> inline void OT(const T0 &x0, const T1 &x1, const T2 &x2, const T3 &x3, const T4 &x4, const T5 &x5, const T6 &x6){OT(x0), OT(x1), OT(x2), OT(x3), OT(x4), OT(x5), OT(x6);}
inline char& RC(char &a, char &b){RC(a), RC(b); return a;}
inline char& RC(char &a, char &b, char &c){RC(a), RC(b), RC(c); return a;}
inline char& RC(char &a, char &b, char &c, char &d){RC(a), RC(b), RC(c), RC(d); return a;}
inline char& RC(char &a, char &b, char &c, char &d, char &e){RC(a), RC(b), RC(c), RC(d), RC(e); return a;}
inline char& RC(char &a, char &b, char &c, char &d, char &e, char &f){RC(a), RC(b), RC(c), RC(d), RC(e), RC(f); return a;}
inline char& RC(char &a, char &b, char &c, char &d, char &e, char &f, char &g){RC(a), RC(b), RC(c), RC(d), RC(e), RC(f), RC(g); return a;}
inline DB& RF(DB &a, DB &b){RF(a), RF(b); return a;}
inline DB& RF(DB &a, DB &b, DB &c){RF(a), RF(b), RF(c); return a;}
inline DB& RF(DB &a, DB &b, DB &c, DB &d){RF(a), RF(b), RF(c), RF(d); return a;}
inline DB& RF(DB &a, DB &b, DB &c, DB &d, DB &e){RF(a), RF(b), RF(c), RF(d), RF(e); return a;}
inline DB& RF(DB &a, DB &b, DB &c, DB &d, DB &e, DB &f){RF(a), RF(b), RF(c), RF(d), RF(e), RF(f); return a;}
inline DB& RF(DB &a, DB &b, DB &c, DB &d, DB &e, DB &f, DB &g){RF(a), RF(b), RF(c), RF(d), RF(e), RF(f), RF(g); return a;}
inline void RS(char *s1, char *s2){RS(s1), RS(s2);}
inline void RS(char *s1, char *s2, char *s3){RS(s1), RS(s2), RS(s3);}

template<class T> inline void RST(T &A){memset(A, 0, sizeof(A));}
template<class T> inline void FLC(T &A, int x){memset(A, x, sizeof(A));}
template<class T> inline void CLR(T &A){A.clear();}

template<class T0, class T1> inline void RST(T0 &A0, T1 &A1){RST(A0), RST(A1);}
template<class T0, class T1, class T2> inline void RST(T0 &A0, T1 &A1, T2 &A2){RST(A0), RST(A1), RST(A2);}
template<class T0, class T1, class T2, class T3> inline void RST(T0 &A0, T1 &A1, T2 &A2, T3 &A3){RST(A0), RST(A1), RST(A2), RST(A3);}
template<class T0, class T1, class T2, class T3, class T4> inline void RST(T0 &A0, T1 &A1, T2 &A2, T3 &A3, T4 &A4){RST(A0), RST(A1), RST(A2), RST(A3), RST(A4);}
template<class T0, class T1, class T2, class T3, class T4, class T5> inline void RST(T0 &A0, T1 &A1, T2 &A2, T3 &A3, T4 &A4, T5 &A5){RST(A0), RST(A1), RST(A2), RST(A3), RST(A4), RST(A5);}
template<class T0, class T1, class T2, class T3, class T4, class T5, class T6> inline void RST(T0 &A0, T1 &A1, T2 &A2, T3 &A3, T4 &A4, T5 &A5, T6 &A6){RST(A0), RST(A1), RST(A2), RST(A3), RST(A4), RST(A5), RST(A6);}
template<class T0, class T1> inline void FLC(T0 &A0, T1 &A1, int x){FLC(A0, x), FLC(A1, x);}
template<class T0, class T1, class T2> inline void FLC(T0 &A0, T1 &A1, T2 &A2, int x){FLC(A0, x), FLC(A1, x), FLC(A2, x);}
template<class T0, class T1, class T2, class T3> inline void FLC(T0 &A0, T1 &A1, T2 &A2, T3 &A3, int x){FLC(A0, x), FLC(A1, x), FLC(A2, x), FLC(A3, x);}
template<class T0, class T1, class T2, class T3, class T4> inline void FLC(T0 &A0, T1 &A1, T2 &A2, T3 &A3, T4 &A4, int x){FLC(A0, x), FLC(A1, x), FLC(A2, x), FLC(A3, x), FLC(A4, x);}
template<class T0, class T1, class T2, class T3, class T4, class T5> inline void FLC(T0 &A0, T1 &A1, T2 &A2, T3 &A3, T4 &A4, T5 &A5, int x){FLC(A0, x), FLC(A1, x), FLC(A2, x), FLC(A3, x), FLC(A4, x), FLC(A5, x);}
template<class T0, class T1, class T2, class T3, class T4, class T5, class T6> inline void FLC(T0 &A0, T1 &A1, T2 &A2, T3 &A3, T4 &A4, T5 &A5, T6 &A6, int x){FLC(A0, x), FLC(A1, x), FLC(A2, x), FLC(A3, x), FLC(A4, x), FLC(A5, x), FLC(A6, x);}
template<class T> inline void CLR(priority_queue<T> &Q){while (!Q.empty()) Q.pop();}
template<class T> inline void CLR(stack<T> &S){while (!S.empty()) S.pop();}
template<class T> inline void CLR(queue<T> &Q){while (!Q.empty()) Q.pop();}

template<class T0, class T1> inline void CLR(T0 &A0, T1 &A1){CLR(A0), CLR(A1);}
template<class T0, class T1, class T2> inline void CLR(T0 &A0, T1 &A1, T2 &A2){CLR(A0), CLR(A1), CLR(A2);}
template<class T0, class T1, class T2, class T3> inline void CLR(T0 &A0, T1 &A1, T2 &A2, T3 &A3){CLR(A0), CLR(A1), CLR(A2), CLR(A3);}
template<class T0, class T1, class T2, class T3, class T4> inline void CLR(T0 &A0, T1 &A1, T2 &A2, T3 &A3, T4 &A4){CLR(A0), CLR(A1), CLR(A2), CLR(A3), CLR(A4);}
template<class T0, class T1, class T2, class T3, class T4, class T5> inline void CLR(T0 &A0, T1 &A1, T2 &A2, T3 &A3, T4 &A4, T5 &A5){CLR(A0), CLR(A1), CLR(A2), CLR(A3), CLR(A4), CLR(A5);}
template<class T0, class T1, class T2, class T3, class T4, class T5, class T6> inline void CLR(T0 &A0, T1 &A1, T2 &A2, T3 &A3, T4 &A4, T5 &A5, T6 &A6){CLR(A0), CLR(A1), CLR(A2), CLR(A3), CLR(A4), CLR(A5), CLR(A6);}
template<class T> inline void CLR(T &A, int n){REP(i, n) CLR(A[i]);}

template<class T> inline bool EPT(T &a){return a.empty();}
template<class T> inline T& SRT(T &A){sort(ALL(A)); return A;}
template<class T, class C> inline T& SRT(T &A, C cmp){sort(ALL(A), cmp); return A;}
template<class T> inline T& RVS(T &A){reverse(ALL(A)); return A;}
template<class T> inline T& UNQQ(T &A){A.resize(unique(ALL(A))-A.begin());return A;}
template<class T> inline T& UNQ(T &A){SRT(A);return UNQQ(A);}
template<class T, class C> inline T& UNQ(T &A, C cmp){SRT(A, cmp);return UNQQ(A);}

/** Constant List .. **/ //{

int MOD = int(1e9) + 7;
const int INF = 0x3f3f3f3f;
const LL INFF = 0x3f3f3f3f3f3f3f3fLL;
const DB EPS = 1e-9;
const DB OO = 1e20;
const DB PI = acos(-1.0); //M_PI;

const int dx[] = {-1, 1, 0, 0};
const int dy[] = {0, 0, 1, -1};

/** Add On .. **/ //{

template<class T> inline bool checkMin(T &a,const T b){return b < a ? a = b, 1 : 0;}
template<class T> inline bool checkMax(T &a,const T b){return a < b ? a = b, 1 : 0;}
template <class T, class C> inline bool checkUpd(T& a, const T b, C c){return c(b,a) ? a = b, 1 : 0;}
template<class T> inline T min(T a, T b, T c){return min(min(a, b), c);}
template<class T> inline T max(T a, T b, T c){return max(max(a, b), c);}
template<class T> inline T min(T a, T b, T c, T d){return min(min(a, b), min(c, d));}
template<class T> inline T max(T a, T b, T c, T d){return max(max(a, b), max(c, d));}
template<class T> inline T sqr(T a){return a*a;}
template<class T> inline T cub(T a){return a*a*a;}
template<class T> inline T ceil(T x, T y){return (x - 1) / y + 1;}
template<class T> T abs(T x){return x>0?x:-x;}
inline int sgn(DB x){return x < -EPS ? -1 : x > EPS;}
inline int sgn(DB x, DB y){return sgn(x - y);}

template<typename T1, typename T2> istream& operator>>(istream& in, pair<T1, T2>& a) {
    in >> a.fi >> a.se;
    return in;
}
template<typename T, size_t N> istream& operator>>(istream& in, array<T, N>& a) {
    REP(i, N) cin >> a[i];
    return in;
}
template<typename T> istream& operator>>(istream& in, vector<T>& a) {
    REP(i, SZ(a)) in >> a[i];
    return in;
}
template<typename T1, typename T2> ostream& operator<<(ostream& out, pair<T1, T2>& a) {
    out << a.fi << " " << a.se;
    return out;
}
template<typename T, size_t N> ostream& operator<<(ostream& out, array<T, N>& a) {
    REP(i, N-1) out << a[i] << " "; if (N) out << a.back();
    return out;
}
template<typename T> ostream& operator<<(ostream& out, vector<T>& a) {
    REP(i, SZ(a)-1) out << a[i] << " "; if (SZ(a)) out << a.back();
    return out;
}

/** I/O Accelerator Interface .. **/ //{
#define g (c=getchar())
#define d isdigit(g)
#define p x=x*10+c-'0'
#define n x=x*10+'0'-c
#define pp l/=10,p
#define nn l/=10,n
template<class T> inline T& RD(T &x){
    char c;while(g,c!='-'&&!isdigit(c));
    if (c=='-'){x='0'-g;while(d)n;}
    else{x=c-'0';while(d)p;}
    return x;
}
inline DB& RF(DB &x){
    char c;while(g,c!='-'&&c!='.'&&!isdigit(c));
    if(c=='-')if(g=='.'){x=0;DB l=1;while(d)nn;x*=l;}
        else{x='0'-c;while(d)n;if(c=='.'){DB l=1;while(d)nn;x*=l;}}
    else if(c=='.'){x=0;DB l=1;while(d)pp;x*=l;}
        else{x=c-'0';while(d)p;if(c=='.'){DB l=1;while(d)pp;x*=l;}}
    return x;
}
#undef nn
#undef pp
#undef n
#undef p
#undef d
#undef g
inline char* RS(char *s){
    scanf("%s", s);
    return s;
}

LL last_ans; int Case; template<class T> inline void OT(const T &x){
    cout << x << endl;
}
namespace lastweapon {}
namespace lastweapon {

namespace NT{
inline LL gcd(LL a, LL b){return b?gcd(b,a%b):a;}
inline LL lcm(LL a, LL b){return a*b/gcd(a,b);}

inline void INC(int &a, int b){a += b; if (a >= MOD) a -= MOD;}
inline int sum(int a, int b){a += b; if (a >= MOD) a -= MOD; return a;}

inline void DEC(int &a, int b){a -= b; if (a < 0) a += MOD;}
inline int dff(int a, int b){a -= b; if (a < 0) a  += MOD; return a;}
inline void MUL(int &a, int b){a = (LL)a * b % MOD;}
inline int pdt(int x,int y) {
    int ret; __asm__ __volatile__ ("\tmull %%ebx\n\tdivl %%ecx\n":"=d"(ret):"a"(x),"b"(y),"c"(MOD));
    return ret;
}

inline int gcd(int m, int n, int &x, int &y){

    x = 1, y = 0; int xx = 0, yy = 1, q;

    while (1){
        q = m / n, m %= n;
        if (!m){x = xx, y = yy; return n;}
        DEC(x, pdt(q, xx)), DEC(y, pdt(q, yy));
        q = n / m, n %= m;
        if (!n) return m;
        DEC(xx, pdt(q, x)), DEC(yy, pdt(q, y));
    }
}

inline int sum(int a, int b, int c){return sum(a, sum(b, c));}
inline int sum(int a, int b, int c, int d){return sum(sum(a, b), sum(c, d));}
inline int pdt(int a, int b, int c){return pdt(a, pdt(b, c));}
inline int pdt(int a, int b, int c, int d){return pdt(pdt(a, b), pdt(c, d));}

inline int pow(int a, LL b){
    int c(1); while (b){
        if (b&1) MUL(c, a);
        MUL(a, a), b >>= 1;
    }
    return c;
}

template<class T> inline T pow(T a, LL b){
    T c(1); while (b){
        if (b&1) c *= a;
        a *= a, b >>= 1;
    }
    return c;
}

template<class T> inline T pow(T a, int b){
    return pow(a, (LL)b);
}

inline int _I(int b){
    int a = MOD, x1 = 0, x2 = 1, q; while (1){
        q = a / b, a %= b;
        if (!a) return x2;
        DEC(x1, pdt(q, x2));

        q = b / a, b %= a;
        if (!b) return x1;
        DEC(x2, pdt(q, x1));
    }
}

inline void DIV(int &a, int b){MUL(a, _I(b));}
inline int qtt(int a, int b){return pdt(a, _I(b));}

struct Int{
    int val;

    operator int() const{return val;}

    Int(int _val = 0):val(_val){
        val %= MOD; if (val < 0) val += MOD;
    }
    Int(LL _val):val(_val){
        _val %= MOD; if (_val < 0) _val += MOD;
        val = _val;
    }

    Int& operator +=(const int& rhs){INC(val, rhs);rTs;}
    Int operator +(const int& rhs) const{return sum(val, rhs);}
    Int& operator -=(const int& rhs){DEC(val, rhs);rTs;}
    Int operator -(const int& rhs) const{return dff(val, rhs);}
    Int& operator *=(const int& rhs){MUL(val, rhs);rTs;}
    Int operator *(const int& rhs) const{return pdt(val, rhs);}
    Int& operator /=(const int& rhs){DIV(val, rhs);rTs;}
    Int operator /(const int& rhs) const{return qtt(val, rhs);}
    Int operator-()const{return MOD-*this;}
};

} using namespace NT;//}

}  // namespace lastweapon

using namespace lastweapon;
using namespace NT;

const int N = int(3e5) + 9;

VI P; bitset<N> isC;
#define ii (i*P[j])
void sieve(){
    FOR(i, 2, N){
        if (!isC[i]) P.PB(i);
        for (int j=0;j<SZ(P)&&ii<N;++j){
            isC[ii]=1; if (!(i%P[j])) break;
        }
    }
}
#undef ii

int main() {
#ifndef ONLINE_JUDGE
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
#endif

    MOD = 998244353;
    sieve();

    int n; LL m; RD(n, m);

    Int z = 0, s = 1, p = 1; LL f = 1;
    REP_1(i, n) {
        if (!isC[i]) f *= i;
        s *= Int(m / f);
        p *= Int(m); z += p - s;
    }
    cout << z << endl;
}

#include <bits/stdc++.h>
using namespace std;

const int N=300005,mod=998244353;
long long dp[N][2];
int to[N];
int primes[N],cnt,vis[N];
inline void get_prime()
{
	for(int i=2; i<=N-5; i++)
	{
		if(!vis[i])
			primes[++cnt]=i;
		for(int j=1; j<=cnt && i*primes[j]<=N-5; j++)
		{
			vis[i*primes[j]]=1;
			if(i%primes[j]==0)
				break;
		}
	}
}

long long gcd(long long x, long long y)
{
	return y==0 ? x : gcd(y, x%y);
}

int main()
{
	long long n,m; scanf("%lld%lld", &n, &m);
	dp[1][0]=m%mod;
	int gg_flag=0;
	long long now=1;
	long long ans=0;
	get_prime();
	vis[1]=1;
	for(int i=2; i<=n; i++)
	{
		if(gg_flag)
		{
			dp[i][0]=0;
			dp[i][1]=(dp[i-1][1]*(m%mod)%mod+dp[i-1][0]*(m%mod)%mod)%mod;
		}
		else
		{
			if(!vis[i])
				now*=i;
			if(now>m)
				gg_flag=1;
			dp[i][0]=dp[i-1][0]*((m/now)%mod)%mod;
			dp[i][1]=(dp[i-1][1]*(m%mod)%mod+dp[i-1][0]*((m-m/now)%mod)%mod)%mod;
		}
		ans=(ans+dp[i][1])%mod;
	}
	cout << ans << '\n';
	return 0;
}

#include <iostream>
#include <vector>
#include <queue>
#include <string>
#include <stack>
#include <unordered_map>
#include <unordered_set>
#include <cmath>
#include <algorithm>
#include <sstream>
#include <set>
#include <numeric>
#define forn(i, n) for (int i = 0; i < int(n); i++)
#define ll long long
using namespace std;
bool is_prime(int x)
{
    for (int i=x/2; i>= 2; i--) {
        if (x%i == 0)
        {
            return false;
        }
    }
    return true;
}
ll modu(ll x, ll mod)
{
    if (x < 0)
    {
        return modu(x+mod,mod);
    }
    else return x%mod;
}
void solve()
{
    ll n,m; cin >> n >> m;
    ll modulo = 998244353;
    ll result = 1;
    ll answer = 0;
    ll x = 1;
    ll c = 1;
    for (int i = 1;  n>= i ; i++)
    {
        if (c != 0 && is_prime(i))
        {
            c = (c*i);
        }
        if (c == 0 || c > m)
        {
            c = 0;
            x = 0;
        }
        else x = (x*((m/c)%modulo))%modulo;
        result = (result*(m%modulo))%modulo;
        answer = modu(answer+result-x,modulo);
    }

    cout << answer << endl;
}
int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    solve();
}

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <cmath>
#include <unordered_map>
#include <unordered_set>
#include <map>
#include <set>
#include <sstream>
#define ll __int128_t
// test1
using namespace std;
long long T,n,m;
const ll maxn = 200005;
inline ll gcd(ll a,ll b) {
    ll r;
    while(b>0) {
        r=a%b;
        a=b;
        b=r;
    }
    return a;
}
const ll mod = 998244353;
void solve() {
    cin >> n >> m;
    ll ans = 0;
    ll now = 1;
    ll num = 1;
    ll xy = 1;
    for(ll i = 1; i <= n; i++) {
        while(ans < 0) {
            ans += mod;
        }
        now = now * m % mod;
        ans = (ans + now) % mod;
        if(num == 0) continue;
        ll g = gcd(num,i);
        if(g == 1)num *= i;
        if(num > m) num = 0;
        if(num == 0) continue;
        ll x = m/num;
        xy = xy * x % mod;
        ans = (ans - xy);
        while(ans < 0) {
            ans += mod;
        }
        ans %= mod;
    }
    while(ans < 0) {
        ans += mod;
    }
    long long res = ans;
    cout << res << '\n';

}
int main() {
    // freopen("input.in","r",stdin);
    ios::sync_with_stdio(false);
    cin.tie(0);
    solve();
    return 0;
}

#include <bits/stdc++.h>
using namespace std;

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
template <typename T>
using o_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
template <typename T>
using o_multiset = tree<T, null_type, less_equal<T>, rb_tree_tag, tree_order_statistics_node_update>;
// member functions :
// 1. order_of_key(k) : number of elements strictly lesser than k
// 2. find_by_order(k) : k-th element in the set
template <class key, class value, class cmp = std::less<key>>
using o_map = __gnu_pbds::tree<key, value, cmp, __gnu_pbds::rb_tree_tag, __gnu_pbds::tree_order_statistics_node_update>;

using i64 = long long;
const i64 Mod = 1000000007;
const i64 MOD = 998244353;
const i64 Inf = 1E18;
const int dx[] = {0,  0, 1, -1, -1, -1,  1, 1};
const int dy[] = {1, -1, 0,  0, -1,  1, -1, 1};

//FOR unordered_map<int,int,custom_hash> TO AVOID FALTU TLE'S COZ OF ANTIHASHES.
struct custom_hash {
    static uint64_t splitmix64(uint64_t x) {
        // http://xorshift.di.unimi.it/splitmix64.c
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }
    size_t operator()(uint64_t x) const {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64(x + FIXED_RANDOM);
    }
};

template <typename T>
T roundup(T a, T b) {
    return(a / b + ((a ^ b) > 0 && a % b));
}

template <typename T>
T choose(T n, T r) {
    if(n < r) return 0LL;
    T res = 1;
    for(T e = 0 ; e < r ; e ++) {
        res = res * (n - e);
        res = res / (e + 1);
    }
    return res;
}

template <typename T>
bool expotwo(T n) {
    T val = (n & (n - 1));
    if(val == 0LL) return true;
    return false;
}

template <typename T>
T modexpo(T b, T e, T mod) {
    T ans = 1;
    while(e) {
        if(e & 1) ans = ((ans % mod) * (b % mod)) % mod;
        b = ((b % mod) * (b % mod)) % mod;
        e >>= 1;
    }
    return ans;
}

template <typename T>
T expo(T b, T e) {
    T ans = 1;
    while(e) {
        if(e & 1) ans = ans * b;
        b = b * b;
        e >>= 1;
    }
    return ans;
}

template <typename T>
bool eprime(T n) {
    if(n < 2) return false;
    for(T e = 2; e * e <= n; e ++) {
        if(n % e == 0) return false;
    }
    return true;
}

template <typename T>
bool eparity(T x, T y) {
    return !((x & 1) ^ (y & 1));
};

template <typename T>
void amax(T& a, T b) {
    a = max(a, b);
}

template <typename T>
void amin(T& a, T b) {
    a = min(a, b);
}

template <typename T>
void add(T& a, T b, T M) {
    a = ((a % M) + (b % M)) % M;
}

template <typename T>
void mul(T& a, T b, T M) {
    a = ((a % M) * (b % M)) % M;
}

template<typename T>
void sub(T& a, T b, T M) {
    a = (a - b + M) % M;
}

/* ************************************************************************ */

set <i64> prime;

void compute() {
    i64 mx = 1E5 + 20;
    vector <int> check(mx);
    for(i64 i = 2; i < mx; i ++) {
        if(check[i]) continue;
        prime.insert(i);
        for(i64 j = i + i; j < mx; j += i) check[j] = 1;
    }
}

void Solution()
{

    i64 n, m; cin >> n >> m;
    i64 lcm = 1, idx = n + 1;
    for(i64 i = 1; i <= n; i ++) {
        if(prime.count(i)) lcm *= i;
        if(lcm > m) {
            idx = i; break;
        }
    }
    vector <i64> gg(n + 1), minus(n + 1, 1);
    gg[1] = 0;
    lcm = 1;
    minus[1] = m;
    for(i64 i = 2; i < idx; i ++) {
        if(prime.count(i)) lcm *= i;
        gg[i] = modexpo(m, i, MOD);
        minus[i] = minus[i - 1];
        mul(minus[i], (m / lcm), MOD);
        gg[i] = (gg[i] - minus[i] + MOD) % MOD;
        gg[i] = (gg[i] + gg[i - 1]) % MOD;
    }
    for(i64 i = idx; i <= n; i ++) {
        gg[i] = modexpo(m, i, MOD);
        add(gg[i], gg[i - 1], MOD);
    }
    cout << gg[n] << '\n';

}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    int Test_case = 1;   //cin >> Test_case;
    compute();
    while(Test_case --) Solution();

}

#include<bits/stdc++.h>
using namespace std;
using ll = long long int;
using ull = unsigned long long int;
const ll M = 998244353;
ll dp[300005];
int p[300005];
vector<int> prime[300005];
void build(int n) {
	fill(p, p+300005, 0);
	for(int i=2;i<=n;i++) {
		if(p[i] == 0) {
			for(int j = i;j<=n;j+=i){
				prime[j].emplace_back(i);
				p[j] = i;
			}
		}
	}
}

ll MUL(ull a, ull b, ull m = M) {
	ull ans = 0;
	while(b > 0) {
		if(b%2 == 1) {
			ans = (ans+a)%M;
		}
		a<<=1, b>>=1;
		a%=M;
	}
	return ans;
}

ll fpow(ll a, ll n) {
	if(n == 0) return 1;
	if(n%2 == 0) return fpow(MUL(a,a), n/2);
	return MUL(a,fpow(MUL(a,a), n/2));
}

int lowbit(int x) {
	//int ans = (x & (-x));
	return (x & (-x));
}

int main(){
	ll n,m;
	scanf("%lld %lld",&n, &m);
	build(n);
	ll ans = 0;
	ll cnt = 1;
	ll mul = 1;
	ll now = 1;
	for(int i=1;i<=n;i++) {
		//printf("i = %d\n",i);
		now = MUL(now, m);
		ans += now;
		if(p[i] == i && mul <= m) mul*=p[i];
		if(mul > m) {
			cnt = 0;
		}
		cnt = MUL(cnt, m/mul);
		//printf("cnt = %lld, ans = %lld, mul = %lld\n",cnt, ans, mul);
		ans = (ans + M - cnt) %M;
	//	printf("cnt = %lld, ans = %lld, mul = %lld\n",cnt, ans, mul);
	}
	printf("%lld\n",ans);

}

#include<bits/stdc++.h>
using namespace std ;
#define int long long
const int M=998244353 ;

int power(int a,int b)
{
    int ans=1 ;
    a=a%M ;
    while(b>0)
    {
        if(b&1)
        {
            ans=(ans*a)%M ;
        }
        a=(a*a)%M ; b=b/2;
    }
    return ans ;
}

void solve()
{
    int n,m,i,j,k ; cin>>n>>m ;
    int a[n+5]={0} ;
    for(i=2;i*i<=n;i++)
    {
        if(a[i]==1) continue ;
        for(j=2*i;j<=n;j+=i) a[j]=1 ;
    }
    int ans=1 ;
    int ans1=0,pp=1 ;
    for(i=1;i<=n;i++)
    {
        if(a[i]==0)
        {
            pp=(pp*i) ;
            if(pp>m) break ;
        }
        int k=(m/pp); k%=M ;
        ans=(ans*k)%M ;
        ans1=((ans1)%M+(ans)%M)%M ;
    }
    int ans2=n ;
    if(m!=1)
    {
        ans2 = (m % M);
        ans2 *= power(m,n)+M-1;
        ans2 %= M;
        ans2 *= power(m-1,M-2);
        ans2 %= M;
    }
    ans2=ans2-ans1 ;
    while(ans2<0) ans2+=M ;
    cout<<(ans2)%M ;
}

int32_t main()
{
    ios::sync_with_stdio(0) ; cin.tie(0) ; cout.tie(0) ;
    int t=1 ; //cin>>t ;
    while(t--) solve() ;
}

// LUOGU_RID: 92518335
#include <bits/stdc++.h>
#define re(i, x, y) for (int i = (x); i < (y); ++i)
#define rep(i, x, y) for (int i = (x); i <= (y); ++i)
#define repp(i, x, y, d) for (int i = (x); i <= (y); i += (d))
#define reep(i, x, y) for (int i = (x); i <= (y); i <<= 1)
#define pe(i, x, y) for (int i = (x) - 1; i >= (y); --i)
#define per(i, x, y) for (int i = (x); i >= (y); --i)
#define rep_e(i, u) for (int i = head[(u)]; i; i = e[i].nxt)
#define vi vector<int>
#define vL vector<LL>
#define vii vector<pii>
#define viL vector<piL>
#define vLi vector<pLi>
#define vLL vector<pLL>
#define eb emplace_back
#define pb pop_back
#define mp make_pair
#define pii pair<int, int>
#define piL pair<int, LL>
#define pLi pair<LL, int>
#define pLL pair<LL, LL>
#define lowbit(x) ((x) & (-(x)))
#define fi first
#define se second
#define all(x) x.begin(), x.end()
#define debug(x) cout << #x << " = " << x << endl
using namespace std;
typedef unsigned int ui;
typedef long long LL;
typedef unsigned long long ULL;
typedef double db;
#define getchar() (SB == TB && (TB = (SB = BB) + fread(BB, 1, 1 << 16, stdin), SB == TB) ? EOF : *SB++)
char BB[1 << 16], *SB = BB, *TB = BB;
template<typename T> void read(T &n) {
    T w = 1;
    n = 0;
    char ch = getchar();
    for ( ; !isdigit(ch); ch = getchar()) {
        if (ch == '-') {
            w = -1;
        }
    }
    for ( ; isdigit(ch); ch = getchar()) {
        n = n * 10 + (ch & 15);
    }
    n *= w;
}
template<typename T> void chkmn(T &a, const T &b) {
    (a > b) && (a = b);
}
template<typename T> void chkmx(T &a, const T &b) {
    (a < b) && (a = b);
}

const int MOD = 998244353;
int adt(const LL &a) {
    return (a % MOD + MOD) % MOD;
}
int inc(const int &a, const int &b) {
    return a + b >= MOD ? a + b - MOD : a + b;
}
int dec(const int &a, const int &b) {
    return a - b < 0 ? a - b + MOD : a - b;
}
int mul(const int &a, const int &b) {
    return 1LL * a * b % MOD;
}
int sqr(const int &a) {
    return 1LL * a * a % MOD;
}
void Adt(LL &a) {
    a = (a % MOD + MOD) % MOD;
}
void Inc(int &a, const int &b) {
    ((a += b) >= MOD) && (a -= MOD);
}
void Dec(int &a, const int &b) {
    ((a -= b) < 0) && (a += MOD);
}
void Mul(int &a, const int &b) {
    a = 1LL * a * b % MOD;
}
void Sqr(int &a) {
    a = 1LL * a * a % MOD;
}
int fsp(int a, int x = MOD - 2) {
    int res = 1;
    for ( ; x; x >>= 1, Sqr(a)) {
        if (x & 1) {
            Mul(res, a);
        }
    }
    return res;
}

const int maxn = 3e5 + 5;
int n;
LL m;
bool v[maxn];
vi P;

int main() {
#ifdef sword
    freopen("test.in", "r", stdin);
#endif

    read(n), read(m);
    int sum = m % MOD, pw = m % MOD, ans = 0;
    LL x = m;
    rep(i, 2, n) {
        if (!v[i]) {
            P.eb(i);
            x /= i;
        }
        Mul(sum, x % MOD), Mul(pw, m % MOD);
        Inc(ans, dec(pw, sum));
        for (auto p : P) {
            if (i * p > n) {
                break ;
            }
            v[i * p] = 1;
            if (i % p == 0) {
                break ;
            }
        }
    }
    printf("%d\n", ans);
    return 0;
}

//
// Created by mrx on 2022/11/12.
//
#include <functional>
#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>
#include <cmath>
#include <queue>
#include <array>
#include <map>
#include <cassert>

using i64 = long long;

template<typename T>
T inverse(T a, T b) {
	T u = 0, v = 1;
	while (a != 0) {
		T t = b / a;
		b -= t * a;
		std::swap(a, b);
		u -= t * v;
		std::swap(u, v);
	}
	assert(b == 1);
	return u;
}

template<typename T>
T power(T a, int b) {
	T ans = 1;
	for (; b; a *= a, b >>= 1) {
		if (b & 1)ans *= a;
	}
	return ans;
}

template<int Mod>
class Modular {
public:
	using Type = int;

	template<typename U>
	static Type norm(U& x) {
		Type v;
		if (-Mod <= x && x < Mod) v = static_cast<Type>(x);
		else v = static_cast<Type>(x % Mod);
		if (v < 0) v += Mod;
		return v;
	}

	constexpr Modular() : value() {}

	int val() const { return value; }

	Modular inv() const {
		return Modular(inverse(value, Mod));
	}

	template<typename U>
	Modular(const U& x) {
		value = norm(x);
	}

	const Type& operator ()() const {
		return value;
	}

	template<typename U>
	explicit operator U() const {
		return static_cast<U>(value);
	}

	Modular& operator +=(const Modular& other) {
		if ((value += other.value) >= Mod) value -= Mod;
		return *this;
	}

	Modular& operator -=(
			const Modular& other) {
		if ((value -= other.value) < 0) value += Mod;
		return *this;
	}

	template<typename U>
	Modular& operator +=(const U& other) { return *this += Modular(other); }

	template<typename U>
	Modular& operator -=(const U& other) { return *this -= Modular(other); }

	Modular& operator ++() { return *this += 1; }

	Modular& operator --() { return *this -= 1; }

	Modular operator ++(int) {
		Modular result(*this);
		*this += 1;
		return result;
	}

	Modular operator --(int) {
		Modular result(*this);
		*this -= 1;
		return result;
	}

	Modular operator -() const { return Modular(-value); }

	template<class ISTREAM_TYPE>
	friend ISTREAM_TYPE& operator >>(ISTREAM_TYPE& is, Modular& rhs) {
		i64 v;
		is >> v;
		rhs = Modular(v);
		return is;
	}

	template<class OSTREAM_TYPE>
	friend OSTREAM_TYPE& operator <<(OSTREAM_TYPE& os, const Modular& rhs) {
		return os << rhs.val();
	}

	Modular& operator *=(const Modular& rhs) {
		value = i64(value) * rhs.value % Mod;
		return *this;
	}

	Modular& operator /=(const Modular& other) { return *this *= Modular(inverse(other.value, Mod)); }

	friend const Type& abs(const Modular& x) { return x.value; }

	friend bool operator ==(const Modular& lhs, const Modular& rhs) { return lhs.value == rhs.value; }

	friend bool operator <(const Modular& lhs, const Modular& rhs) { return lhs.value < rhs.value; }

	bool operator ==(const Modular& rhs) { return *this == rhs.value; }

	template<typename U>
	bool operator ==(U rhs) { return *this == Modular(rhs); }

	template<typename U>
	friend bool operator ==(U lhs, const Modular& rhs) { return Modular(lhs) == rhs; }

	bool operator !=(const Modular& rhs) { return *this != rhs; }

	template<typename U>
	bool operator !=(U rhs) { return *this != rhs; }

	template<typename U>
	friend bool operator !=(U lhs, const Modular& rhs) { return lhs != rhs; }

	bool operator <(const Modular& rhs) { return this->value < rhs.value; }

	Modular operator +(const Modular& rhs) { return Modular(*this) += rhs; }

	template<typename U>
	Modular operator +(U rhs) { return Modular(*this) += rhs; }

	template<typename U>
	friend Modular operator +(U lhs, const Modular& rhs) { return Modular(lhs) += rhs; }

	Modular operator -(const Modular& rhs) { return Modular(*this) -= rhs; }

	template<typename U>
	Modular operator -(U rhs) { return Modular(*this) -= rhs; }

	template<typename U>
	friend Modular operator -(U lhs, const Modular& rhs) { return Modular(lhs) -= rhs; }

	Modular operator *(const Modular& rhs) { return Modular(*this) *= rhs; }

	template<typename U>
	Modular operator *(U rhs) { return Modular(*this) *= rhs; }

	template<typename U>
	friend Modular operator *(U lhs, const Modular& rhs) { return Modular(lhs) *= rhs; }

	Modular operator /(const Modular& rhs) { return Modular(*this) /= rhs; }

	template<typename U>
	Modular operator /(U rhs) { return Modular(*this) /= rhs; }

	template<typename U>
	friend Modular operator /(U lhs, const Modular& rhs) { return Modular(lhs) /= rhs; }

private:
	Type value;
};

using Modint = Modular<998244353>;

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	std::cout.tie(nullptr);

	i64 n, m;

	std::cin >> n >> m;

	std::vector<int> vis(n + 1), prime;
	for (int i = 2; i <= n; ++i) {
		if (!vis[i])prime.push_back(i);
		for (int j = 0; j < prime.size() && prime[j] * i <= n; ++j) {
			vis[prime[j] * i] = 1;
			if (i % prime[j] == 0)break;
		}
	}

	Modint tot = 0;
	for (int i = 1; i <= n; ++i) {
		tot += power(Modint(m), i);
	}

	Modint ans = tot;
	int ptr = 0;
	i64 cur = 1;
	Modint cnt = 1;
	for (int i = 1; i <= n; ++i) {
		if (cur > m)continue;
		while (prime[ptr] < i && ptr < prime.size())ptr++;
		if (i == prime[ptr])cur *= prime[ptr];
		cnt *= m / cur;
		ans -= cnt;
	}

	std::cout << ans << '\n';

	return 0;
}

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inf INT_MAX
#define N 300005
ll mod=998244353;
ll n,m,ans=0,x,y,l,r,s,z;
ll f[N],g[N];
bool b[N];
ll cnt=0,p[N];
template<typename T>inline void read(T &n){
	T w=1; n=0; char ch=getchar();
	while (!isdigit(ch) && ch!=EOF){ if (ch=='-') w=-1; ch=getchar(); }
	while (isdigit(ch) && ch!=EOF){ n=(n<<3)+(n<<1)+(ch&15); ch=getchar(); }
	n*=w;
}
template<typename T>inline void write(T x){
	if (x==0){ putchar('0'); return ; }
	T tmp;
	if (x>0) tmp=x;
	else tmp=-x;
	if (x<0) putchar('-');
	char F[105];
	long long cnt=0;
	while (tmp){
		F[++cnt]=tmp%10+48;
		tmp/=10;
	}
	while (cnt) putchar(F[cnt--]);
}
void prime(ll n){
	b[1]=true;
	for (ll i=2; i<=n; i++){
		if (!b[i]){
			cnt++;
			p[cnt]=i;
		}
		for (ll j=1; j<=cnt && i*p[j]<=n; j++){
			b[i*p[j]]=true;
			if (i%p[j]==0) break;
		}
	}
	return ;
}
int main(){
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
    ll i,j;
    read(n); read(m);
    prime(n);
    ans=0;
    x=y=1;
    f[0]=1;
    for (i=1; i<=n; i++){
    	x=x*(m%mod)%mod;
    	if (!b[i]) f[i]=f[i-1]*i;
    	else f[i]=f[i-1];
    	if (f[i]>m) f[i]=m+1;
    	y=y*((m/f[i])%mod)%mod;
    	ans=ans+x-y;
    	ans%=mod;
	}
	ans=(ans%mod+mod)%mod;
	write(ans);
    return 0;
}

#include<bits/stdc++.h>
#define int long long
using namespace std;
namespace IO{
    template<typename T>
    inline void read(T &x){
        x=0;
        int f=1;
        char ch=getchar();
        while(ch>'9'||ch<'0'){
            if(ch=='-'){
                f=-1;
            }
            ch=getchar();
        }
        while(ch>='0'&&ch<='9'){
            x=x*10+(ch-'0');
            ch=getchar();
        }
        x=f==1?x:-x;
    }
    template<typename T>
    inline void write(T x){
        if(x<0){
            putchar('-');
            x=-x;
        }
        if(x>=10){
            write(x/10);
        }
        putchar(x%10+'0');
    }
    template<typename T>
    inline void write_endl(T x){
        write(x);
        putchar('\n');
    }
    template<typename T>
    inline void write_space(T x){
        write(x);
        putchar(' ');
    }
}
using namespace IO;
const int mod=998244353,N=3e5+10;
int n,m,prime[N],isprime[N],cnt;
void init(){
    for(int i=2;i<=n;i++){
        if(!isprime[i]){
            prime[++cnt]=i;
        }
        for(int j=1;j<=cnt&&prime[j]*i<=n;j++){
            isprime[i*prime[j]]=1;
            if(i%prime[j]==0){
                break;
            }
        }
    }
}
void solve(){
    read(n),read(m);
    init();
    int ans=1,sum=0,s=1;
    for(int i=1;i<=n;i++){
        if(!isprime[i]){
            s=s*i;
        }
        if(s>m||s<0){
            break;
        }
        ans=ans*(m/s%mod)%mod;
        sum=(sum+ans)%mod;
    }
    int ans1=1,sum1=0;
    for(int i=1;i<=n;i++){
        ans1=ans1*(m%mod)%mod;
        sum1=(sum1+ans1)%mod;
    }
    ans=(sum1-sum+mod)%mod;
    write_endl(ans);
}
signed main(){
#ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
#endif
    solve();
    return 0;
}

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef pair<int,ll> pil;
//typedef complex<double> C;
// simplified

const int P = 998244353;
const int N=3e5+5;
const int M=5e5+5;
const int INF=0x3f3f3f3f;
const double EPS=1e-15;
const double PI= acos(-1);
bool isprime[N];
int prime[N],cnt=0;
// functions

ll qpow(ll a,ll b)
{
    a%=P;
    ll res = 1;
    while(b){
        if(b&1){
            res *= a ,res%=P;
        }
        a*=a,a%=P;
        b/=2;
    }
    return res;
}

void find_prime(int n)
{
	memset(isprime, 1, sizeof(isprime));
	isprime[1] = 0;
	for (int i = 2; i <= n; i++) {
		if (isprime[i]){
			prime[cnt++] = i;
        }
		for (int j = 0;j<cnt&&prime[j]<=n/i; j++) {
			isprime[i * prime[j]] = 0;
			if (i % prime[j] == 0){
                break;
            }
		}
	}
}

int main()
{
    //ios::sync_with_stdio(0), cin.tie(0);
    // clock_t st = clock();
    // freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
    // code start

    ll n,m;
    cin >> n >> m;

    find_prime(n+1);

    ll res = 0;
    ll base = m%P;
    for(int i=1;i<=n;i++){
        res += base , res%=P;
        base *= (m%P) ,base %=P;
    }
    ll mul = 1 ,cnt = 1;
    for(int i=1;i<=n;i++){
        if(isprime[i])mul*=i;
        if(mul>m)break;
        cnt *= (m/mul)%P;
        cnt %= P;
        res -= cnt;
        if(res<0)res+= P;
    }

    cout << res;

    //code end
    // cerr << clock() - st << "ms" << endl;
    // fclose(stdin);
    // fclose(stdout);

    return 0;
}

// LUOGU_RID: 94227078
#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
const int N=300005;
const ll mod=998244353;
bool vis[N];
ll n,m,prime[N],tot=0,c[N],g[N];
void getprime(){
	memset(vis,1,sizeof(vis));
	for(int i=1;i<=n;i++)prime[i]=1;
	g[1]=1;
	for(ll i=2;i<=n;i++){
		if(vis[i]){
			prime[i]=i;
			for(int j=i+i;j<=n;j+=i)vis[j]=0;
		}
		g[i]=g[i-1]*prime[i];
	}
}
int main(){
	cin>>n>>m;
	getprime();
	ll r1=1,r2=1;
	ll res=0;
	for(int i=1;i<=n;i++){
		if(g[i]>m)r1=0;
		else r1=(r1*((m/g[i])%mod))%mod;
		r2=(r2*(m%mod))%mod;
		res=(res+(r2-r1+mod)%mod+mod)%mod;
	}
	cout<<res<<endl;
	return 0;
}
//´æÔÚambiguous:´æÔÚÄ³¸öaiÓë2-iÖÐÄ³¸öÊý»¥ÖÊ
//²»´æÔÚambiguous£ºÃ¿Ò»¸öaiÓë2-iËùÓÐÊý²»»¥ÖÊ£¬¼´aiÊÇ2-iËùÓÐËØÊýµÄ¹«±¶Êý
//g[i]=2-iËùÓÐËØÊýµÄ³Ë»ý
//ÎªÁË±£Ö¤²»´æÔÚambiguous£¬aiµÄ¿ÉÄÜÊýÁ¿Îª£ºm/g[i]
//³¤¶ÈÎªnµÄÐòÁÐ£¬²»´æÔÚambiguousµÄÇé¿ö£º(m/g[i])µÄ³Ë»ý£¬i´Ó1µ½n£¬ÉèÎªr1
//³¤¶ÈÎªn£¬´æÔÚambiguousµÄÇé¿ö£ºmµÄn´Î·½-r1
//Çó³¤¶È1-nµÄÐòÁÐÖÐambiguousÊýÁ¿×ÜºÍ

#include <iostream>
#include <vector>
#include <string>
#include <cmath>
#include <algorithm>
using namespace std;
#define pb push_back
typedef long long ll;
typedef vector<vector<int> > vvi;
typedef vector<int> vi;
typedef vector<long long> vll;

ll P = 998244353;
ll fast_exp(ll n, ll m, ll k){
    ll ans = 1;
    ll factor = n%k;
    while(m!=0){
        if(m%2==1){
            ans = (ans%k) * (factor%k);
            ans = ans % k;
        }
        factor = (factor%k)*(factor%k);
        factor %= k;
        m/=2;
    }
    return ans%k;
}
int main() {
    ll n, m;
    cin >> n >> m;

    vector<bool> prime;
    for(ll i=0; i<=n; i++) prime.pb(true);
    ll ind = 2;
    while(ind<=n){
        if(!prime[ind]){
            ind++;
            continue;
        }
        for(ll i=2*ind; i<=n; i+=ind) prime[i] = false;
        ind++;
    }

    ll sum = m%P; //non-ambiguous arrays
    ll denominator = 1; // product of primes <= k
    ll product = m%P; // k/(denominator)
    for(ll i=2; i<=n; i++){
        bool is_prime = prime[i];
        if(is_prime){
            denominator = denominator*i;
        }
        if(product==0) break;
        product = (product % P) * ((m/denominator)%P);
        product = product % P;
        sum = sum + product;
        sum = sum % P;
    }
    ll total=0; //total possible arrays
    for(ll i=1; i<=n; i++){
        total = total%P + fast_exp(m,i,P)%P;
        total = total%P;
    }
    if(m==1){
        cout << (n-1)%P;
        return 0;
    }
    cout << (total - sum + P)%P;
}

#include<bits/stdc++.h>
    #define int long long
    #define pb push_back
    using namespace std;
    const long long MOD = 998244353;
    int t;
    long long n,m;

    long long po[300005];

    void fillpo(long long n, long long m){
        int x = 1;
        po[0] = 1;
        for(int i = 1; i <= n; ++i){
            po[i] = (po[i-1] * (m % MOD)) % MOD;
        }
    }

    signed main(){
    //    freopen("INP.txt", "r", stdin);
    //    freopen("OUT2.txt", "w", stdout);
        ios_base::sync_with_stdio(0);
        cin.tie(0);
        cout.tie(0);
            cin >> n >> m;
            fillpo(n, m);
    //        for(int i = 1; i <= n; ++i) cout << po[i] << ' ';
    //        cout << endl;
            long long ans = 0, minu = m;
            minu %= MOD;
            for(int i = 2; i <= n; ++i){
                ans = (ans + po[i]) % MOD;
                if(i >= 37){
                    continue;
                }
                else if(i >= 31){
                    minu *= ((m / 200560490130) % MOD);
                    minu = minu % MOD;
                    ans -= minu;
    //                if(ans < 0) ans += MOD;
                }
                else if(i >= 29){
                    minu *= ((m / 6469693230) % MOD);
                    minu = minu % MOD;
                    ans -= minu;
    //                if(ans < 0) ans += MOD;
                }
                else if(i >= 23){
                    minu *= ((m / 223092870) % MOD);
                    minu = minu % MOD;
                    ans -= minu;
    //                if(ans < 0) ans += MOD;
                }
                else if(i >= 19){
                    minu *= ((m / 9699690) % MOD);
                    minu = minu % MOD;
                    ans -= minu;
    //                if(ans < 0) ans += MOD;
                }
                else if(i >= 17){
                    minu *= ((m / 510510) % MOD);
                    minu = minu % MOD;
                    ans -= minu;
    //                if(ans < 0) ans += MOD;
                }
                else if(i >= 13){
                    minu *= ((m / 30030) % MOD);
                    minu = minu % MOD;
                    ans -= minu;
    //                if(ans < 0) ans += MOD;
                }
                else if(i >= 11){
                    minu *= ((m / 2310) % MOD);
                    minu = minu % MOD;
                    ans -= minu;
    //                if(ans < 0) ans += MOD;
                }
                else if(i >= 7){
                    minu *= ((m / 210) % MOD);
                    minu = minu % MOD;
                    ans -= minu;
    //                if(ans < 0) ans += MOD;
                }
                else if(i >= 5){
                    minu *= ((m / 30) % MOD);
                    minu = minu % MOD;
                    ans -= minu;
    //                if(ans < 0) ans += MOD;
                }
                else if(i >= 3){
                    minu *= ((m / 6) % MOD);
                    minu = minu % MOD;
                    ans -= minu;
    //                if(ans < 0) ans += MOD;
                }
                else if(i >= 2){
                    minu *= ((m / 2) % MOD);
                    minu = minu % MOD;
                    ans -= minu;
    //                if(ans < 0) ans += MOD;
                }
                else{
    //                cout << ans << endl;
                    continue;
                }
    //            cout << ans << endl;
            }
            ans %= MOD;
            if(ans < 0) ans += MOD;
            cout << ans << endl;
        return 0;
    }

#include <bits/stdc++.h>
using namespace std;
#define endl "\n"
#define x first
#define y second
typedef pair<int,int> PII;
typedef long long LL;
typedef unsigned long long ULL;
const int mod = 998244353;
const int N = 2e6 + 10 , M = 2 * N, P =  131;

//debug清单
LL n, m;
LL dp[N][2];
map<int, LL> lm;
//dp[i][0] 表示明确的

int prm[N], pct;     // primes[]存储所有素数
bool pst[N];         // st[x]存储x是否被筛掉

void get_primes(int n)
{
    for (int i = 2; i <= n; i ++ )
    {
        if (!pst[i]) prm[pct ++ ] = i;
        for (int j = 0; prm[j] <= n / i; j ++ )
        {
            pst[prm[j] * i] = true;
            if (i % prm[j] == 0) break;
        }
	}
	pct --;
}

void solve()
{
    //初始化，既数组，也变量：

    //输入：
	cin >> n >> m;
	//cout << 3e5 << " " << (LL)1e12 << endl;

	get_primes(n);
	LL lcm = 1;
	dp[0][0] = 1, dp[0][1] = 0;
	for(LL i = 1; i <= n; i ++)
	{
		if(!pst[i]) lcm *= i;
		if(lcm > m)
		{
			dp[i][1] = (dp[i - 1][0] * (m % mod) % mod + dp[i - 1][1] * (m % mod) % mod) % mod;
			dp[i][0] = 0;
		}
		else
		{
			dp[i][0] = dp[i - 1][0] * ((m / lcm) % mod) % mod;
			dp[i][1] = (dp[i - 1][0] * ((m - m / lcm) % mod) % mod + dp[i - 1][1] * (m % mod) % mod) % mod;
		}
	//	cnt += (cnt * (m / lcm % mod)) % mod;
	}
//我傻了……
//题读错了hh
	LL ans = 0;
	for(int i = 1; i <= n; i ++)
	{
		ans = (ans + dp[i][1]) % mod;
	}
	cout << ans << endl;

}
int main(){
std::ios::sync_with_stdio(false);std::cin.tie(0);
solve();}

#include<bits/stdc++.h>
using namespace std;

#define int int64_t

const int N = 200010, mod = 998244353;
int n, m;
int a[N];

int powmod(int x, int y)
{
	x %= mod;
	int ans = 1;
	while(y)
	{
		if(y & 1) ans = ans * x % mod;
		x = x * x % mod;
		y >>= 1;
	}
	return ans;
}

int gcd(int x, int y) {
    if (!x) return y;
    if (!y) return x;
    return gcd(y, x%y);
}

int32_t main(){
	cin >> n >> m;
	int ans = 0;
	for(int i=2;i<=n;i++) ans = (ans + powmod(m, i)) % mod;

	int x = 0;
	int cnt = 1, flag = 0;
	for(int i=2;i<=n;i++)
	{
		if(!x) x = i;
		else if (gcd(x, i) == 1){
			if(x <= m/i) x *= i;
			else break;
		}

		cnt = cnt * ((m / x) % mod) % mod;
		ans = (ans - (m % mod) * cnt % mod + mod) % mod;
	}
	cout << ans << endl;
}

#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
const int N=300005;
const ll mod=998244353;
ll n,m,prime[N],tot=0,vis[N],c[N],g[N];
void getprime(){
	memset(vis,0,sizeof(vis));
	for(ll i=2;i<=n;i++){
		if(!vis[i]){
			vis[i]=1;
			prime[++tot]=i;
		}
		for(int j=1;j<=tot;j++){
			if(i*prime[j]>n)break;
			vis[i*prime[j]]=1;
		}
		c[i]=tot;
	}
}
void cal(){
	ll t=0;
	ll s=1;
	g[1]=1;
	for(ll i=2;i<=n;i++){
		for(int j=t+1;j<=c[i];j++){
			s=s*prime[j];
		}
		t=c[i];
		g[i]=s;
	}
}
int main(){
	cin>>n>>m;
	getprime();
//	cout<<"1\n";
//	for(int i=1;i<=n;i++)cout<<i<<" "<<c[i]<<endl;
	cal();
//	cout<<"2\n";
//	for(int i=1;i<=n;i++)cout<<i<<" "<<c[i]<<" "<<g[i]<<endl;
	ll r1=1,r2=1;
	ll res=0;
	for(int i=1;i<=n;i++){
		if(g[i]>m)r1=0;
		else r1=(r1*((m/g[i])%mod))%mod;
		r2=(r2*(m%mod))%mod;
		res=(res+(r2-r1+mod)%mod+mod)%mod;
	}
	cout<<res<<endl;
	return 0;
}

//i hate _____
#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/detail/standard_policies.hpp>

using namespace __gnu_pbds;
using namespace std;

#define ll long long int
#define lll __int128_t
#define ld long double
#define pb push_back
#define ii pair<int,int>
#define endl "\n"
double pi = 2 * acos(0.0) ;

template<typename T>
ostream& operator<<(ostream &os, const vector<T> &v) {
    os << '{';
    for (const auto &x : v) os << " " << x;
        return os << '}';
}

typedef tree<
int,
null_type,
less<int>,
rb_tree_tag,
tree_order_statistics_node_update>
ordered_set;

const ll mod = 998244353;
ll n, m;

bool isprime(int x){
    for (int i = 2; i*i <= x; i++) if (x%i == 0)
        return false;
    return true;
}

ll get_nbad(ll p){
    ll res = (m/p) % mod;
    return res;
}

void solve(){
    cin >> n >> m;
    ll p = 1;
    ll bad = 0;
    ll tmp = m % mod;
    for (ll i = 2; i <= n ; i++) {
        if (isprime(i)) p *= i;
        if (p > m) break;
        ll t = get_nbad(p);
        tmp = (t*tmp) % mod;
        bad = (bad + tmp) % mod;
    }
    m %= mod;
    tmp = m;
    ll ans = 0;
    for (int i = 2; i <= n; i++) {
        tmp = (tmp*m) % mod;
        ans = (ans + tmp) % mod;
    }
    ans = (ans - bad + mod) % mod;
    cout << ans << endl;
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL); cout.tie(NULL);

    #ifndef ONLINE_JUDGE
        freopen("input.txt", "r", stdin);
        freopen("output.txt", "w", stdout);
    #endif

    int test_cases = 1;
    // cin >> test_cases;

    for (int tc = 1 ; tc <= test_cases ; tc++){

        //cout << "Case " << tc << ": ";
        solve();
        //printf("Case %d: %.10lf\n",tc,ans);

    }

    return 0;
}
/*
    problems are the sign of life
*/

#include<bits/stdc++.h>
using namespace std;
//#include <ext/pb_ds/assoc_container.hpp> // Common file
//#include <ext/pb_ds/tree_policy.hpp> // Including tree_order_statistics_node_update
//using namespace __gnu_pbds; //  order of key(keys strictly less than)  // find_by_order
//typedef tree<long long,null_type,less<>,rb_tree_tag,tree_order_statistics_node_update> ordered_set;
//typedef tree<long long, null_type, less_equal<>, rb_tree_tag, tree_order_statistics_node_update> indexed_multiset;
//IF WA CHECK FOR : -
// 1 > EDGE CASES LIKE N=1 , N=0
// 2 > SIGNED INTEGER OVERFLOW IN MOD
// 3 > CHECK THE CODE FOR LOGICAL ERRORS AND SEG FAULTS
// 4 > READ THE PS ONCE AGAIN , if having double diff less than 1e-8 is same.
// 5 > You Have got AC .
// 6 > Don't use int it's pathetic
#define ll long long
#define all(x) x.begin(),x.end()
#define NUM (ll)998244353
#define inf (long long)(2e18)
#define ff first
#define ss second
#define f(i,a,b) for(ll i=a;(i)<(long long)(b);(i)++)
#define fr(i,a,b) for(ll i=a;(i)>=(long long)(b);(i)--)
#define it(b)  for(auto &it:(b))
#define pb push_back
#define mp make_pair
typedef vector<ll> vll;
typedef pair<ll,ll> pll;
ll binpow( ll base , ll ex,ll mod=NUM) {
    ll ans = 1;base = base % mod;
    if(base==0){
        return 0;
    }
    while (ex > 0) {
        if (ex % 2 == 1) {
            ans = (ans * base) % mod;
        }
        base = (base * base) % mod;
        ex = ex / 2;
    }
    return ans;
}
void read(vll &arr,ll n) {
    if (arr.size() != n) { arr.assign(n, 0); }for (int i = 0; i < n; i++)cin >> arr[i];
}
inline ll min(ll a,ll b){
    if(a>b)return b;return a;
}
inline ll max(ll a, ll b){
    if(a>b)return a;return b;
}
inline ll dif(ll a,ll b) {
    if (a > b)return a - b;return b - a;
}
long long gcd(long long a,long long b) {
    if (b == 0)return a;return gcd(b, a % b);
}
long long lcm(long long a,long long b) {
    long long k = gcd(a, b);return (a * b) / k;
}
vector<long long >prime;
void sieveOferatosthenes(long long  MAX)
{
    vll lps(MAX+1);
    vector<bool> pri(MAX+1,true);
    pri[1]=false;
    lps[1]=1;lps[2]=2;
    for (long long  p = 2; p * p <= MAX; p++) {
        if (pri[p]) {
            lps[p] = p;
            for (long long i = p * p; i <= MAX; i += p) {
                pri[i] = false;
                if (lps[i] == 0) {
                    lps[i] = p;
                }
            }
        }
    }
    for(long long  i=1;i<=MAX;i++) {
        if (pri[i]) {
            prime.push_back(i);
            lps[i]=i;
        }
    }
}
void solve() {
    ll n,m;cin>>n>>m;
    ll res=m;
    // res +=res*now;
    ll pt=0;ll num = 1;
    ll prev=m%NUM;
    f(i,2,n+1){
        if(i>=prime[pt]) {
            num = num*prime[pt++];
        }
        ll now = (prev*((m/num)%NUM))%NUM;
        res+=(prev*((m/num)%NUM))%NUM;
        prev=now;
        res%=NUM;
        if(m/num==0){
            break;
        }
    }
    //cout<<res<<endl;
    // res should be giving the number of non-ambiguous arrays
    ll tot=0;
    f(i,1,n+1){
        tot+=(binpow(m,i))%NUM;tot%=NUM;
    }
    cout<<(tot-res+NUM)%NUM<<endl;
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << showpoint;
    cout << setprecision(12);
    long long test_m = 1;
    //int k=1;cin >> test_m;
    //I WILL WIN .
    sieveOferatosthenes(4e5);
    while (test_m--) {
        //cout<<"Case #"<<k++<<": ";
        solve();
    }
}

// LUOGU_RID: 93606292
#include <bits/stdc++.h>
using namespace std;

#define int long long
#define F first
#define S second
#define sz(x) ((int)x.size())
#define all(x) x.begin(),x.end()
#define rall(x) x.rbegin(),x.rend()
#define sqr(x) ((x)*(x))
#define odd(x) ((x)&1)
#define even(x) (!odd(x))

template<class T>bool chkmax(T &a,T b){return b>a?a=b,true:false;}
template<class T>bool chkmin(T &a,T b){return b<a?a=b,true:false;}

constexpr int inf=2e18;
constexpr int mod=998244353;

struct mint{
	int x;
	mint(int x=0):x(norm(x%mod)){}
	int val()const{
		return x;
	}
	mint operator-()const{
		return mint(norm(mod-x));
	}
	int norm(int x)const{
		if(x<0){
			x+=mod;
		}
		if(x>=mod){
			x-=mod;
		}
		return x;
	}
	mint pow(int x)const{
		mint res=1;
		mint cur=*this;
		while(x){
			if(odd(x)){
				res*=cur;
			}
			cur*=cur;
			x/=2;
		}
		return res;
	}
	mint inv()const{
		assert(x!=0);
		return pow(mod-2);
	}
	mint &operator*=(const mint &rhs){
		x=(long long)(x)*rhs.x%mod;
		return *this;
	}
	mint &operator+=(const mint &rhs){
		x=norm(x+rhs.x);
		return *this;
	}
	mint &operator-=(const mint &rhs){
		x=norm(x-rhs.x);
		return *this;
	}
	mint &operator/=(const mint &rhs){
		return *this*=rhs.inv();
	}
	friend mint operator*(const mint &lhs,const mint &rhs){
		mint res=lhs;
		res*=rhs;
		return res;
	}
	friend mint operator+(const mint &lhs,const mint &rhs){
		mint res=lhs;
		res+=rhs;
		return res;
	}
	friend mint operator-(const mint &lhs,const mint &rhs){
		mint res=lhs;
		res-=rhs;
		return res;
	}
	friend mint operator/(const mint &lhs,const mint &rhs){
		mint res=lhs;
		res/=rhs;
		return res;
	}
	friend istream &operator>>(istream &is,mint &a){
		long long v;
		is>>v;
		a=mint(v);
		return is;
	}
	friend ostream &operator<<(ostream &os,const mint &a){
		return os<<a.val();
	}
};

bool prime(int n){
	if(n==1){
		return false;
	}
	for(int i=2;i*i<=n;i++){
		if(n%i==0){
			return false;
		}
	}
	return true;
}

template<class T>
T fpow(T a,int b){
	T res=1;
	for(;b;b>>=1){
		if(odd(b)){
			res*=a;
		}
		a*=a;
	}
	return res;
}

void solve(){
	int n,m;
	cin>>n>>m;
	mint ans=m,sum=m;
	int now=1;
	for(int i=2;i<=n;i++){
		if(prime(i)){
			now*=i;
			if(now>m){
				break;
			}
		}
		sum*=m/now;
		ans+=sum;
	}
	mint tot=0;
	for(int i=1;i<=n;i++){
		tot+=fpow<mint>(m,i);
	}
	cout<<tot-ans<<"\n";
}

signed main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	solve();
	return 0;
}

//#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#define fastio std::cin.tie(0), std::cout.tie(0), std::ios_base::sync_with_stdio(false)
#define rep(a, b, c, d) for (int a = b; a < c; a += d)
#define INF ((1ll << 62) - 1)
#define all(x) x.begin(), x.end()
#define sz(x) x.size()
#define pb push_back
using namespace std;
#define MN 200000
#define int __int128
int mod = 998244353;

int bin_pow(int a, int p) {
    int res = 1;
    while (p) {
        if (p % 2) {
            p--;
            res *= a;
            res %= mod;
        } else {
            a *= a;
            a %= mod;
            p /= 2;
        }
    }
    return res;
}
long long n, m;

int mgcd(int a, int b) {
    if (b == 0) return a;
    return mgcd(b, a % b);
}

int mlcm(int a, int b) {
    return (a * b) / mgcd(a, b);
}
auto main() -> signed {
    fastio;
    int res = 0;
    cin >> n >> m;
    int cur[300000];
    cur[0] = 1;
    for (int i = 2; i <= n; ++i) {
        res += bin_pow(m, i);
        res %= mod;
    }
    int c = m;
    for (int i = 1; i < n; ++i) {
        if (mgcd(i + 1, cur[i - 1]) == 1) {
            cur[i] = mlcm(cur[i - 1], i + 1);
        } else {
            cur[i] = cur[i - 1];
        }
        if (cur[i] > m) break;
        c *= m / cur[i];
        c %= mod;
        res -= c;
        res = (res % mod + mod) % mod;
    }
    cout << (long long)res;
}

#include<bits/stdc++.h>
using namespace std;

struct ModInt {
  static unsigned M;
  unsigned x;
  ModInt() : x(0U) {}
  ModInt(unsigned x_) : x(x_ % M) {}
  ModInt(unsigned long long x_) : x(x_ % M) {}
  ModInt(int x_) : x(((x_ %= static_cast<int>(M)) < 0) ? (x_ + static_cast<int>(M)) : x_) {}
  ModInt(long long x_) : x(((x_ %= static_cast<long long>(M)) < 0) ? (x_ + static_cast<long long>(M)) : x_) {}
  ModInt &operator+=(const ModInt &a) { x = ((x += a.x) >= M) ? (x - M) : x; return *this; }
  ModInt &operator-=(const ModInt &a) { x = ((x -= a.x) >= M) ? (x + M) : x; return *this; }
  ModInt &operator*=(const ModInt &a) { x = (static_cast<unsigned long long>(x) * a.x) % M; return *this; }
  ModInt &operator/=(const ModInt &a) { return (*this *= a.inv()); }
  ModInt pow(long long e) const {
    if (e < 0) return inv().pow(-e);
    ModInt a = *this, b = 1U; for (; e; e >>= 1) { if (e & 1) b *= a; a *= a; } return b;
  }
  ModInt inv() const {
    unsigned a = M, b = x; int y = 0, z = 1;
    for (; b; ) { const unsigned q = a / b; const unsigned c = a - q * b; a = b; b = c; const int w = y - static_cast<int>(q) * z; y = z; z = w; }
    assert(a == 1U); return ModInt(y);
  }
  ModInt operator+() const { return *this; }
  ModInt operator-() const { ModInt a; a.x = x ? (M - x) : 0U; return a; }
  ModInt operator+(const ModInt &a) const { return (ModInt(*this) += a); }
  ModInt operator-(const ModInt &a) const { return (ModInt(*this) -= a); }
  ModInt operator*(const ModInt &a) const { return (ModInt(*this) *= a); }
  ModInt operator/(const ModInt &a) const { return (ModInt(*this) /= a); }
  template <class T> friend ModInt operator+(T a, const ModInt &b) { return (ModInt(a) += b); }
  template <class T> friend ModInt operator-(T a, const ModInt &b) { return (ModInt(a) -= b); }
  template <class T> friend ModInt operator*(T a, const ModInt &b) { return (ModInt(a) *= b); }
  template <class T> friend ModInt operator/(T a, const ModInt &b) { return (ModInt(a) /= b); }
  explicit operator bool() const { return x; }
  bool operator==(const ModInt &a) const { return (x == a.x); }
  bool operator!=(const ModInt &a) const { return (x != a.x); }
  friend std::ostream &operator<<(std::ostream &os, const ModInt &a) { return os << a.x; }
};
unsigned ModInt::M = 998244353;

#define ll long long
#define pi pair<ll,ll>
const int N=3e5+100;
ll t,n,m,k;
string s;
ll a[N], b[N];

int pr[N],prc;
bool notpr[N];

void eluer()
{
	for (int i = 2; i < N; i++)
	{
		if(!notpr[i]) pr[prc++]=i;
		for (int j = 0; j < prc && pr[j]*i<=N; j++)
		{
			notpr[pr[j]*i] = 1;
			if(i%pr[j]==0) break;
		}
	}
}

int main()
{
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	eluer();
	cin>>n>>t;
	ModInt m=t, ans=0, cur=1;
	ll div=1;
	for(int k=1;k<=n;k++) {
    ans += m.pow(k);
		if(div<=t && !notpr[k]) div*=k;
		if(div<=t) {
      ans-=cur*ModInt(t/div);
		  cur*=ModInt(t/div);
    }
	}
	cout<<ans<<"\n";

	return 0;
}

// CAUTION REVIEW

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int dim = 1000002,mod=998244353 ;
int n,m;
bool prim[dim];

void ciur ()
{
    for (int i=3;i*i<=n;i+=2)
    if (prim[i]==0)
        for (int j=i*i;j<=n;j+=i)
        prim[j]=1;
}

int inm(int x,int y)
{
    x%=mod;
    y%=mod;
    x=(x*y)%mod;
    return x;
}

void solve ()
{
    cin>>n>>m;
    int sol=0,putere=m;
    for (int i=2; i<=n; i++)
    {
        putere=inm(putere,m)%mod;
        sol=(sol+putere)%mod;
    }
    ciur();
    int y=m%mod,mult=1;
    for (int i=2; i<=n && mult<=m; i++)
    {
        if (i==2||(i%2==1 && prim[i]==0))
            mult=mult*i;
        if (mult>m)
            mult=m+1;
        int nr=(m/mult)%mod;
        y=(y*nr)%mod;
        sol-=y;
        if (sol<0)
            sol+=mod;
    }
    cout<<sol;
}

int32_t main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    int t=1;
    // cin >> t;
    //  cin.get();
    while (t--)
    {
        solve();
        cout<<'\n';
    }
}

#include <algorithm>
#include <bitset>
#include <chrono>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;

using ll = long long;
using vi = vector<int>;
using vl = vector<ll>;
using vvi = vector<vi>;
using pii = pair<int, int>;
using vii = vector<pii>;
using pll = pair<ll, ll>;

#define bit(x, k) (1ll & ((x) >> (k)))
#define off(x, k) ((x) & ~(1ll << (k)))
#define on(x, k) ((x) | (1ll << (k)))

mt19937_64 rng(
    (unsigned long long)chrono::steady_clock::now().time_since_epoch().count());

template <ll mod> struct mint {
  mint() : v(0) {}
  mint(ll tv) : v(((tv % mod) + mod) % mod) {}

  explicit operator ll() const { return v; }

  mint &operator*=(mint const &other) {
    v = (v * other.v) % mod;
    return *this;
  }

  mint &operator+=(mint const &other) {
    v = (v + other.v) % mod;
    return *this;
  }

  mint &operator/=(mint const &other) {
    v = (v * inv(other.v)) % mod;
    return *this;
  }

  mint &operator-=(mint const &other) {
    v = (((v - other.v) % mod) + mod) % mod;
    return *this;
  }

  mint pow(mint const &b) {
    mint res{pow(v, b.v)};
    return res;
  }

  mint operator-() const { return mint(-v); }
  mint &operator++() { return *this += 1; }
  mint &operator--() { return *this -= 1; }

  friend mint operator+(mint a, mint const &b) { return a += b; }
  friend mint operator-(mint a, mint const &b) { return a -= b; }
  friend mint operator*(mint a, mint const &b) { return a *= b; }
  friend mint operator/(mint a, mint const &b) { return a /= b; }
  friend bool operator==(mint const &a, mint const &b) { return a.v == b.v; }
  friend bool operator!=(mint const &a, mint const &b) { return a.v != b.v; }
  friend bool operator<(mint const &a, mint const &b) { return a.v < b.v; }

  friend istream &operator>>(istream &is, mint &a) {
    ll t;
    cin >> t;
    a = mint{t};
    return is;
  }

  friend ostream &operator<<(ostream &os, mint const &a) {
    os << a.v << " ";
    return os;
  }

private:
  ll v;

  // computes a**x % mod
  ll pow(ll a, ll x) {
    if (x == 0)
      return 1;
    if (x == 1)
      return a;

    ll y = pow(a * a % mod, x / 2);
    if ((x & 1) == 1)
      y = (y * a) % mod;
    return y;
  }

  // solves ax + by = gcd(a,b)
  // return gcd(a,b)
  // returns coeffecients x and y
  ll ext_gcd(ll a, ll b, ll &x, ll &y) {
    if (b == 0) {
      x = 1;
      y = 0;
      return a;
    }

    ll x1, y1;
    ll g = ext_gcd(b, a % b, x1, y1);

    // b x1 + [a - ((a/b) * b] y1
    // b x1 + a y1 - ((a/b) y1 * b
    x = y1;
    y = x1 - (a / b) * y1;
    return g;
  }

  // computes the modular inverse of a % mod | x * a % mod = 1
  ll inv(ll a) {
    ll x, y;
    ll g = ext_gcd(a, mod, x, y);
    // assert g == 1 - always true if mod is prime.
    x = ((x % mod) + mod) % mod;
    return x;
  }
};

const ll mod = 998'244'353;

using mm = mint<mod>;

/// true if a is prime in O(sqrt(a))
bool prime(ll a) {
  for (ll i = 2; (i * i) <= a; ++i)
    if (a % i == 0)
      return false;
  return true;
}

int32_t main(int32_t argc, char **argv) {
  ios_base::sync_with_stdio(0);
  cin.tie(0);

  // Keeping N as an mint is pointless because it's constraint to be less than
  // 3*10**5 Keeping M as a mint is harmful because - we try to calculate M /
  // (p1 p2 p3 .. pk) to count all the integers from 1 .. M - will be inaccurate
  // if M > mod
  ll N{}, M{};
  cin >> N >> M;

  // rather than counting the number of ambiguous arrays we subtract the number
  // of unambigous arrays from the number of total arrays.

  // the total number of arrays

  mm ans{0};
  for (mm i = 1; i < (N + 1); ++i) {
    ans += mm{M}.pow(i);
  }

  // t is the number of unambigous arrays exactly length i
  mm t{1};

  // run in O(N sqrt(N))

  // we can achieve O(N) if we use a seive instead of naive prime factorization.

  // the minimum prime factor for every number i in segment [2 ... N]
  vi lp(N + 1);
  vi pr; // all primes found in the segmetn [2 ... N]
  for (int i = 2; i <= N; ++i) {
    if (lp[i] == 0) { // case 1: lp[i] == 0 - the current i is prime since we
                      // haven't found smaller factors for it.
      lp[i] = i;
      pr.push_back(i);
    }
    // case 2: lp[i] != 0 - i is composite and minimum prime factor is lp[i]
    // in both cases update all lp[x] for all x divisible by i
    for (int j = 0; i * pr[j] <= N; ++j) {
      lp[i * pr[j]] =
          pr[j]; // we only update multiples of i and primes less than lp[i]
      if (pr[j] == lp[i]) {
        break;
      }
    }
  }

  // prefix_current[i] is the prefix product of all primes [p1, p2 ... pk] in
  // the range [1...i]
  vl prefix_current(N + 1, 1);
  for (ll i = 2; i <= N; ++i) {
    prefix_current[i] = prefix_current[i - 1];

    if (lp[i] == i && prefix_current[i] <= M) {
      prefix_current[i] *= i;
    }
  }

  for (ll i = 1; i <= N; ++i) {
    // once the prefix product is greater than M - there are no multiples in the
    // range [1 ... M] and hence no more unambiguous arrays.
    if (prefix_current[i] > M)
      break;

    // we want integer floor division here rather than division under mod.
    ll num_elements = M / prefix_current[i];

    // cout << "prefix_product = " << prefix_current[i] << endl;
    // cout << i << " " << num_elements << endl;

    // update t: for every unambiguous array length i, we can construct
    // num_elements unambiguous arrays of length i + 1
    t *= mm{num_elements};

    // subtract unambiguous arrays of length i from the total number of arrays
    ans -= t;
  }

  cout << ans << endl;

  return 0;
}

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define lld long double
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define fastio() ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL)
#define ff first
#define ss second
#define pb push_back
#define mp make_pair
#define pii pair<int,int>
#define PI 3.1415926535897932384626
#define mod 1000000007
#define ms(arr, v) memset(arr, v, sizeof(arr))
#define deb(x) cout<<x<<"\n";
#define deB(x,y) cout<<x<<" "<<y<<"\n";
#define Deb(x,y,z) cout<<x<<" "<<y<<" "<<z<<"\n"
#define YES cout<<"YES\n";
#define Yes cout<<"Yes\n";
#define NO cout<<"NO\n";
#define No cout<<"No\n";
#define bct(x) __builtin_popcountll(x)
#define all(v) (v).begin(),(v).end()
#define mk(arr,n,type)  type *arr=new type[n];
template <typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

// cout << s.order_of_key(2) << endl; // the number of elements in the s less than 2
// cout << *s.find_by_order(0) << endl; // print the 0-th smallest number in s(0-based)

#ifndef ONLINE_JUDGE
#define debug(x) cerr << #x <<" "; _print(x); cerr << endl;
#else
#define debug(x)
#endif

void _print(ll t) {cerr << t;}
void _print(int t) {cerr << t;}
void _print(string t) {cerr << t;}
void _print(char t) {cerr << t;}
void _print(lld t) {cerr << t;}
void _print(double t) {cerr << t;}
void _print(ull t) {cerr << t;}

template <class T, class V> void _print(pair <T, V> p);
template <class T> void _print(vector <T> v);
template <class T> void _print(set <T> v);
template <class T, class V> void _print(map <T, V> v);
template <class T> void _print(multiset <T> v);
template<class T> void _print(priority_queue<T> pq);
template<class T> void _print(priority_queue<T, vector<T>, greater<T>> pq);
template <class T, class V> void _print(pair <T, V> p) {cerr << "{"; _print(p.ff); cerr << ","; _print(p.ss); cerr << "}";}
template <class T> void _print(vector <T> v) {cerr << "[ "; for (T i : v) {_print(i); cerr << " ";} cerr << "]";}
template <class T> void _print(set <T> v) {cerr << "[ "; for (T i : v) {_print(i); cerr << " ";} cerr << "]";}
template <class T> void _print(multiset <T> v) {cerr << "[ "; for (T i : v) {_print(i); cerr << " ";} cerr << "]";}
template <class T, class V> void _print(map <T, V> v) {cerr << "[ "; for (auto i : v) {_print(i); cerr << " ";} cerr << "]";}
template<typename A> void _print(priority_queue<A> pq) { if (!pq.empty()) { queue<A> t; cerr << "T["; while (pq.size() != 1) { _print(pq.top()); cerr << ","; t.push(pq.top()); pq.pop(); } _print(pq.top()); cerr << "]B"; t.push(pq.top()); pq.pop(); while (!t.empty()) { pq.push(t.front()); t.pop(); } } else { cerr << "F[]B"; } }
template<typename A> void _print(priority_queue<A, vector<A>, greater<A>> pq) { if (!pq.empty()) { queue<A> t; cerr << "T["; while (pq.size() != 1) { _print(pq.top()); cerr << ","; t.push(pq.top()); pq.pop(); } _print(pq.top()); cerr << "]B"; t.push(pq.top()); pq.pop(); while (!t.empty()) { pq.push(t.front()); t.pop(); } } else { cerr << "F[]B"; } }

/*-------------------------------------------------------------------------------------------*/
ll gcd(ll a, ll b) {if (b > a) {return gcd(b, a);} if (b == 0) {return a;} return gcd(b, a % b);}
ll expo(ll a, ll b, ll m) {ll res = 1; while (b > 0) {if (b & 1)res = ((res % m) * (a % m)) % m; a = ((a % m) * (a % m)) % m; b = b >> 1;} return res;}
ll mminvprime(ll a, ll b) {return expo(a, b - 2, b);}
ll mod_add(ll a, ll b, ll m) {a = a % m; b = b % m; return ((((a % m) + (b % m)) % m) + m) % m;}
ll mod_mul(ll a, ll b, ll m) {a = a % m; b = b % m; return ((((a % m) * (b % m)) % m) + m) % m;}
ll mod_sub(ll a, ll b, ll m) {a = a % m; b = b % m; return ((((a % m) - (b % m)) % m) + m) % m;}
ll mod_div(ll a, ll b, ll m) {a = a % m; b = b % m; return (mod_mul(a, mminvprime(b, m), m) + m) % m;}  //only for prime m
/*--------------------------------------------------------------------------------------------*/

const int N = (3e5) + 5;

const ll mod1 = 998244353;

int32_t main() {

#ifndef ONLINE_JUDGE
	freopen("Error.txt", "w", stderr);
#endif
	fastio();

	ll n, m;
	cin >> n >> m;

	vector<int> is_prine(N, 1);

	is_prine[0] = 0, is_prine[1] = 0;

	for (ll i = 2; i * (ll)i < N; i++) {
		if (is_prine[i] == 1) {
			for (ll j = i * i; j * (ll)j < N; j += i) {
				is_prine[j] = 0;
			}
		}
	}

	// Total ambiguous array = (Total number of array)- (Total number of unabiguous array).

	// total= m+(m^2)+(m^3)+(m^4)+.........+(m^n)  ---> Gp

	ll total = 0;

	for (ll i = 1; i <= n; i++) {
		ll val = expo(m, i, (ll)mod1);

		total = mod_add(total, val, (ll)mod1);
	}

	total %= mod1;

	debug(total);

	// To find --> number of unambiguous arrays

	/*
	    _,_,_,_,_,_,_,_,_,x,_,_,_,_,_,_,_,_,_,_
	    1,2,3,4,5,6,7,8,9,10

	    What is the value of x such that if it gets left shifted to any of the positions if an element get deleted such that its
	    gcd with that particular index is always >1.

	    --> This is only possible if x is a multiple of all the indicies left to it and are prime number.
	    --> x has to be a multiple of (2*3*5*7) , so that at any position its gcd with that index is greater than 1.
	*/

	ll unambiguous = 0;

	ll productOfPrimes = 1, ans = 1;

	for (ll i = 1; i <= n; i++) {
		if (is_prine[i] == 1) {
			productOfPrimes *= (ll)i;
		}

		debug(productOfPrimes);

		if (productOfPrimes > m) {  // Numbers have to be in the range from 1 to m .
			break;
		}

		ll canHave = m / productOfPrimes; // Numbers from [1,m] which are multiple of product of primes.

		canHave %= mod1;

		debug(canHave);

		ans *= canHave;
		ans %= mod1;

		unambiguous += ans;
		unambiguous %= mod1;
	}

	ll ambiguous = ((total - unambiguous) + (mod1)) % mod1;

	cout << ambiguous << endl;

	return 0;
}

#include <bits/stdc++.h>
using namespace std;
#define ll long long

const long long N = 3e5 + 10, MOD = 998244353;
long long Factor[N], cnt[N], res[N];

// Calculates (a ^ b) mod p
long long modular_exponentiation(long long a, long long b, long long p)
{
    a = a % p;
    long long res = 1;
    while (b)
    {
        if (b & 1)
            res = (res * a) % p;
        a = (a * a) % p;
        b = b >> 1;
    }
    return (res % p);
}

/*
    (a^-1) % p
    a and p should be co-prime
    uses Fermat’s little theorem
    a^(M - 1) ≅ 1 (mod M)
    a^(-1) ≅ a^(M - 2) (mod M)

*/
long long mod_inverse(long long a, long long p)
{
    return modular_exponentiation(a, p - 2, p);
}

void solve()
{
    ll n, m, cleared = 0, total = 1, ans, pt, GCD;
    cin >> n >> m;
    if (m == 1)
    {
        cout << n - 1 << "\n";
        return;
    }
    total = (total * modular_exponentiation(m, 2LL, MOD)) % MOD;
    total = (total * (modular_exponentiation(m, n - 1, MOD) - 1 + MOD)) % MOD;
    total = (total * mod_inverse(m - 1, MOD)) % MOD;

    Factor[1] = 1;
    res[1] = m;
    for (ll i = 2; i <= n; i++)
    {
        if (Factor[i - 1] > m)
            Factor[i] = Factor[i - 1];
        else
        {
            GCD = __gcd(Factor[i - 1], i);
            if (GCD >= 2)
                Factor[i] = Factor[i - 1];
            else
                Factor[i] = (i * Factor[i - 1]);
        }
        if (Factor[i] > m)
            Factor[i] = (long long)(1e18);
    }
    for (ll i = 1; i <= n; i++)
        cnt[i] = m / Factor[i];
    for (ll i = 2; i <= n; i++)
        res[i] = ((cnt[i] % MOD) * (res[i - 1] % MOD)) % MOD;
    for (ll i = 2; i <= n; i++)
        cleared = (cleared + res[i]) % MOD;
    ans = (total - cleared + MOD) % MOD;
    cout << ans << "\n";
    return;
}

int main()
{
    long long T = 1;
    for (long long i = 1; i <= T; i++)
    {
        solve();
    }
    return 0;
}

#include<bits/stdc++.h>
using namespace std;
#define int long long
template<typename G>inline void read(G&x) {G f=1;x=0;char ch=getchar();while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();if(ch=='-') f=-1,ch=getchar();while(ch>='0'&&ch<='9') x=x*10+(ch^48),ch=getchar();x*=f;}
const int MAXN=3e5+5,p=998244353;
int T,n,m,ans,mul,sum,cnt,pri[MAXN];
bool f[MAXN];
int qpow(int x,int y) {
	int res=1;
	while(y) {
		if(y&1) res=res*x%p;
		x=x*x%p,y>>=1;
	}
	return res;
}
void euler() {
	for(int i=2;i<=3e5;++i) {
		if(!f[i]) {
			pri[++cnt]=i;
		}
		for(int j=1;j<=cnt;++j) {
			if(i*pri[j]>3e5) break;
			f[i*pri[j]]=1;
			if(i%pri[j]==0) break;
		}
	}
}
int now,tot;
signed main() {
	euler();
	read(n),read(m);ans=sum=m%p,mul=1;now=tot=m%p;
	for(int i=2;i<=n;++i) {
		if(!f[i]&&mul<=m) mul*=i;
		now=(now*(m%p))%p,tot=(tot+now)%p;
		ans=(ans*((m/mul)%p))%p,sum=(sum+ans)%p;
	}
	printf("%lld\n",((tot-sum)%p+p)%p);
	return 0;
}

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define pii pair<int,int>
#define pll pair<long long,long long>
#define IOS ios::sync_with_stdio(0), cin.tie(0),cout.tie(0)
#define endl "\n"
const ll inf=1ll<<60;
const int mod=998244353;
mt19937 rnd(std::chrono::system_clock::now().time_since_epoch().count());
//uniform_int_distribution<long long> dist(0, 100000);//随机数限定范围:dist(rnd);
inline int lowbit(int x){return x&(-x);}
const int N=300010;
ll n, m, k[N], dp[N];
const int maxn = 1e6+10;//0 base
int prime[maxn], p[maxn];//prime记录素数
int primes(int n)
{
    int top = 0;
    for(int i = 2; i <= n; i++){
        if(!p[i]) prime[top++]=i;
        for(int j = 0; j < top && i * prime[j] <= n; j++){
            p[i * prime[j]] = 1;
            if(i % prime[j] == 0) break;
        }
    }
    return top;//返回素数个数-1
}
ll qp(ll x, ll k){
	ll res=1;
	for(;k;k>>=1,x*=x,x%=mod){
		if(k&1) res*=x,res%=mod;
	}
	return res;
}
void solve(){
	cin>>n>>m;
	ll res=1, now=0;
	for(ll i=1;i<=n;i++){
		if(res<=m&&prime[now] == i) res *= i,now++;
		k[i]=m - m / res, k[i] %= mod;
//		cout<<k[i]<<"<--\n";
	}
	m %= mod;
	dp[1] = 0;
	dp[2] = k[2] * m % mod;
	ll sum = dp[1] + dp[2];
	sum %= mod;
	for(int i=3;i<=n;i++){
		dp[i] = dp[i-1] * m % mod + k[i] * (qp(m, i - 1) + mod - dp[i-1]) % mod, dp[i] %= mod;
		sum += dp[i], sum %= mod;
//		cout<<"dp"<<i<<" = "<<dp[i]<<" "<<qp(m,i-1)<<"<--\n";
	}
	cout<<sum<<"\n";
}
signed main(){
	IOS;
	primes(200010);
	int _test=1,_tot=0;
//	cin>>_test;
	while(_test--){
//		printf("Case #%d: \n",++_tot);
		solve();
	}
	return 0;
}

#include <iostream>
#include <map>
#include <algorithm>
#include <math.h>
#include <set>
#include <vector>
#include <string>
#include <queue>
#include <stack>
#define ll long long int
using namespace std;
int isPrime(ll n)
{
ll k=0;
for(ll i=2;i*i<=n;i++)
if(n%i==0)
k++;
if(k>0)
    return 0;
    else
    return 1;
}

int main()
{

    ll n,m;
    cin>>n>>m;
ll P=998244353;
 ll ans=0;
 ll sum=0;
ll a=1;
for(ll i=1;i<=n;i++)
{
    a=(a*(m%P))%P;
    ans=(ans+a+P)%P;

}

ll prime=1;
ll answer=1;
for(ll i=1;i<=n;i++)
{
    if(isPrime(i))
    {
prime=prime*i;

    }
    if(prime>m)
    break;
    answer=answer%P*((m/prime)%P);
    sum=(sum+answer)%P;
}
cout<<(ans-sum+P)%P<<endl;

    return 0;
}

#include <bits/stdc++.h>
#include <cassert>
using namespace std;
#define ll long long
#define ull unsigned long long
#define ld long double
#define pii pair<int, int>
#define pll pair<ll, ll>
#define fr first
#define sc second
#define vt vector
#define all(c) (c).begin(), (c).end()
#define sz(x) (int)(x).size()

#define EXPAND( x ) x // Use this if MS Visual Studio doesn't expand __VA_ARGS__ correctly
#define F_OR(i, a, b, s) for (int i = (a); (s) > 0 ? i < (b) : i > (b); i += (s))
#define F_OR1(e) F_OR(i, 0, e, 1)
#define F_OR2(i, e) F_OR(i, 0, e, 1)
#define F_OR3(i, b, e) F_OR(i, b, e, 1)
#define F_OR4(i, b, e, s) F_OR(i, b, e, s)
#define GET5(a, b, c, d, e, ...) e
#define F_ORC(...) EXPAND( GET5(__VA_ARGS__, F_OR4, F_OR3, F_OR2, F_OR1) )
#define FOR(...) EXPAND( F_ORC(__VA_ARGS__ )(__VA_ARGS__) )
#define EACH(x, a) for (auto& x : a)

const double EPS = 1e-9;
const int INF = 1e9 + 7;
const int MOD = 998244353;
const int dy[] = { 0, 0, 1, -1, 1, 1, -1, -1 };
const int dx[] = { 1, -1, 0, 0, 1, -1, 1, -1 };

ll gcd(ll a, ll b) {
	if (b == 0) return a;
	else return gcd(b, a % b);
}

ll lcm(ll a, ll b) {
	return a * b / gcd(a, b);
}

const int MAX = 1e6;

bool isPrime[MAX + 1];
vector<int> prime(1, 2);

void getPrime() {
	fill(isPrime + 2, isPrime + MAX + 1, 1);

	for (ll i = 4; i <= MAX; i += 2)
		isPrime[i] = 0;
	for (ll i = 3; i <= MAX; i++) {
		if (isPrime[i]) prime.push_back(i);
		for (ll j = i * i; j <= MAX; j += i * 2)
			isPrime[j] = 0;
	}
}

ll n, m;

int main() {
	#ifndef ONLINE_JUDGE
	freopen("/Users/jeongwoo-kyung/Programming/CP-Codes/input.txt", "r", stdin);
	freopen("/Users/jeongwoo-kyung/Programming/CP-Codes/output.txt", "w", stdout);
	#endif

	cin.tie(NULL); cout.tie(NULL);
	ios_base::sync_with_stdio(false);

    getPrime();

    cin >> n >> m;

    vt<ll> non(n + 1);
    non[1] = m % MOD;

    ll lc = 1;
    for (ll i = 2; i <= n; i++) {
        if (isPrime[i])
            lc = lcm(lc, i);

        ll cnt = m / lc;
        non[i] = non[i - 1] * (cnt % MOD) % MOD;
    }

    vt<ll> sum(n + 1);
    sum[1] = m % MOD;
    for (int i = 2; i <= n; i++) {
        sum[i] = sum[i - 1] * (m % MOD) % MOD;
    }

    ll ans = 0;
    for (int i = 1; i <= n; i++) {
        ans = (ans + sum[i] - non[i]) % MOD;
    }

    cout << (ans + MOD) % MOD;

	return 0;
}

// Problem Link:
// Status

#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;
using namespace std;

#define ff              first
#define ss              second
#define ll                              long long int
#define ld                              long double
#define pb              push_back
#define mp              make_pair
#define mt              make_tuple
#define pii             pair<ll,ll>
#define vi              vector<ll>
#define vs                              vector<string>
#define mii             map<int,int>
#define pqb             priority_queue<int>
#define pqs             priority_queue<int,vi,greater<int> >
#define setbits(x)      __builtin_popcountll(x)
// #define mod             998244353
#define inf             1e18
#define ps(x,y)         fixed<<setprecision(y)<<x
#define mk(arr,n,type)  type *arr=new type[n];
#define range(a,b)              substr(a,b-a+1)
#define w(x)            int x; cin>>x; while(x--)
#define trace(x)                cerr<<#x<<": "<<x<<" "<<endl;
#define ip(x)           ll x;cin>>x
#define endl                    "\n"
#define pq_max          priority_queue<ll>
#define pq_min          priority_queue<ll,vi,greater<ll> >
#define Mid(l,r)        (l+(r-l)/2)
#define loop(i,a,b)     for(int i=(a);i<=(b);i++)
#define looprev(i,a,b)  for(int i=(a);i>=(b);i--)
#define log(args...)    { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); err(_it, args); }
#define logarr(arr,a,b) for(int z=(a);z<=(b);z++) cout<<(arr[z])<<" ";cout<<endl;
#define token(str,ch)   (std::istringstream var((str)); vs v; string t; while(getline((var), t, (ch))) {v.pb(t);} return v;)
#define vvi vector<vector<ll>>
#define all(a) (a).begin(),(a).end()

vs tokenizer(string str,char ch) {std::istringstream var((str)); vs v; string t; while(getline((var), t, (ch))) {v.pb(t);} return v;}

void err(istream_iterator<string> it) {}
template<typename T, typename... Args>
void err(istream_iterator<string> it, T a, Args... args) {
        cout << *it << " = " << a << endl;
        err(++it, args...);
}

template<typename T>
using minpq = priority_queue<T, vector<T>, greater<T>>;

mt19937                 rng(chrono::steady_clock::now().time_since_epoch().count());

typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> pbds;

void file_i_o()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
        #ifndef ONLINE_JUDGE
            // freopen("input.txt", "r", stdin);
            // freopen("output.txt", "w", stdout);
        #endif
}

const ll N = 13e5 + 1, mod = 998244353;
vi p;
vi spf(N+1, 0);

void LSieve()
{
        for(ll x=2; x<=N; x++)
        {
                if( spf[x] == 0 )
                {
                        spf[x] = x;
                        p.pb(x);
                }
                for(ll j=0; j < (ll)p.size() and p[j] <= spf[x] and (p[j] * x <= N); j++ )
                        spf[ p[j]*x ] = min( spf[x], p[j] ); // or set it to p[j] as p[j] <= spf[x]
        }
        return;
}

ll get_count(ll nume, ll deno, ll mod)
{
        if(nume < deno) return 0;
        ll ans = ( nume / deno);
        return ans%mod;
}

ll pwmd(ll a, ll b, ll m){
    if( b == 0) return 1;

    ll sp = pwmd(a, b/2, m);
    ll ans = (sp*sp)%m;
    if( b&1LL ) ans = (ans*a)%m;
    return ans;
}

void solve()
{
        // Logic:
        // ambi:-> >= 2 ways property
        // In 2 ways property Pattren
        // Signal: ask complement qs

        // By construction [1, 1, 1, 1] is always a poss
        // for any array, what's the ppty that
        // exactly 1 construction is poss?
        // This is the compl.

        // Now, what does this mean?
        // This means, atleast in 1 posn, 1 isnt present
        // Say, What does that mean?
        // There exists aj s.t
        // after k( <= j-2 ) opns, it goes to j - k place
        // and gcd( j-k, aj) = 1
        // => aj is coprime to all primes in the prime fact of j-k

        // If such an aj exists,
        // Then another resolution order is:
        // [ 1, 1, ..., ktimes, 1, j-k, 1, 1, .., 1 ]
        // => no such j should exists.

        // Num of unambig arrays = Num of arrays s.t
        // ai is a multiple of all primes <= i for all i >= 2

        // Ans = Total - Num of unAmb

        // xi = num of ways can cosntruct ai <= m and div by all primes <= i
        // Let p1, p2, p3 are 3 primes <= i
        // xi = m/lcm( p1, p2, p3 ) = m / p1*p2*p3
        // Ans = m^n - [ prod(xi) ]

        // n = 4, m = 2
        // len = 1 -> 2 -> 2
        // len = 2 -> 2*(2/2) -> 2
        // len = 3 -> 2*(2/2)*(2/6)*(2/6)
        // len = 4 -> 2*(2/2)*(2/6)*(2/6)

        // Total = 2 + 4 + 8 + 16 = 30
        // m + m1 + m2 + m3 = (m^4 - 1) / (m - 1)

        ip(n);
        ip(m);

        vi dp(n+1, 1), pre(n+1, 1);

        for(ll i=2; i<=n; i++){
                pre[i] = (pre[i-1] * ( spf[i] == i ? i : 1 )) ;
                if(pre[i]>1e12){
                        pre[i] = 1e12+5 ;
                }
        }

        ll k = m%mod;

        dp[1] = k;

        ll ans = dp[1];

        for(int i=2; i<=n; i++)
        {
                ll x = get_count( m ,pre[i] ,mod ) ;
                dp[i] = (dp[i-1] * x)%mod;
                ans = (ans + dp[i])%mod;
        }

        ll total = 0;
        for(ll i=1; i<=n; i++)
                total = (total + pwmd(k, i, mod))%mod;

        ans = (total - ans + mod)%mod;
        cout << ans << "\n";

}

int32_t main()
{
        file_i_o();
        LSieve();
        // w(t)
                solve();

        return 0;
}

#include <bits/stdc++.h>
using namespace std;
#define M 1000005
#define int long long
const int mod=998244353;
int T,n,m,a[M],b[M],fg,k,f[M],ans,nd[M],cnt,all,sum,f1,f2;
int qpow(int x,int y) {
	x%=mod; int res=1,base=x;
	while(y) {
		if(y&1) res*=base,res%=mod;
		base*=base,base%=mod,y/=2;
	} return res;
}
signed main() {
	cin>>n>>m;
	for(int i=1;i<=n;i++) all=(all+qpow(m,i))%mod;
	nd[1]=1;
	for(int i=2;i<=40;i++) {
		nd[i]=nd[i-1];
		if(__gcd(i,nd[i-1])==1) nd[i]*=i;
	} f1=1;
	for(int l=1;l<=min(n,(int)40);l++) {
		f2=m/nd[l]; f2%=mod;
		f1*=f2; f1%=mod;
		sum+=f1,sum%=mod;
	}
	all=(all-sum+mod)%mod;
	cout<<all<<endl;
	return 0;
}
/*
1 2
*/

#include<cstdio>
#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
#define ll long long
#define lowbit(x) x&(-x)
#define endl '\n'
#define wk is zqx ta die
const ll mod = 998244353;
ll s[300005];
ll add(ll a, ll b) {
	ll res = 0;
	while (b) {
		if (b & 1) {
			res = res + a;
			res %= mod;
		}
		a = a + a;
		a %= mod;
		b >>= 1;
	}
	return res;
}
ll pow(ll a, ll b) {
	ll res = 1;
	while (b) {
		if (b & 1) {
			res = add(res, a);
		}
		a = add(a, a);
		b >>= 1;
	}
	return res;
}
bool ispri[300005];
int main() {
	std::ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	//	for (int i = 2; i <= 300000; i++) {
	//		for (int j = i; j <= 300000; j += i) {
	//			phi[j]++;
	//		}
	//	}
	for (int i = 2; i <= 300000; i++) {
		if (ispri[i] == 0) {
			for (int j = i + i; j <= 300000; j += i) {
				ispri[j] = 1;
			}
		}
	}
	ll n, m;
	cin >> n >> m;
	ll sum = 1;
	for (int i = 2; i <= n; i++) {
		if (ispri[i] == 0) {
			sum = sum * i;
			if (sum > m) {
				break;
			}
		}
		s[i] = m / sum;
	}
	for (int i = 3; i <= n; i++) {
		s[i] = add(s[i], s[i - 1]);
		//		cout << s[i] << endl;
	}
	ll ans = 0;
	ll mo = m % mod;
//	ans = (pow(m, n + 1) - 2 - mo + mod) % mod;
//	cout << ans << endl;
	ll cnt = add(m, m);
	for (int i = 2; i <= n; i++) {
		ans = ans + cnt;
		ans %= mod;
		cnt = add(cnt, m);
	}
	for (int i = 2; i <= n; i++) {
		ans = ans - add(s[i], m);
		ans = (ans + mod) % mod;
	}
	cout << ans << endl;
	return 0;
}

#include <iostream>
#include <vector>
#include <queue>
#include <string>
#include <stack>
#include <unordered_map>
#include <unordered_set>
#include <cmath>
#include <algorithm>
#include <sstream>
#include <set>
#include <numeric>
#define forn(i, n) for (int i = 0; i < int(n); i++)
#define ll long long
using namespace std;
bool is_prime(int x)
{
    for (int i=x/2; i>= 2; i--) {
        if (x%i == 0)
        {
            return false;
        }
    }
    return true;
}
ll modu(ll x, ll mod)
{
    if (x < 0)
    {
        return modu(x+mod,mod);
    }
    else return x%mod;
}
void solve()
{
    ll n,m; cin >> n >> m;
    ll modulo = 998244353;
    ll result = 1;
    ll answer = 0;
    ll x = 1;
    ll c = 1;
    for (int i = 1;  n>= i ; i++)
    {
        if (c != 0 && is_prime(i))
        {
            c = (c*i);
        }
        if (c == 0 || c > m)
        {
            c = 0;
            x = 0;
        }
        else x = (x*((m/c)%modulo))%modulo;
        result = (result*(m%modulo))%modulo;
        answer = modu(answer+result-x,modulo);
    }

    cout << answer << endl;
}
int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    solve();
}

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int mod = 998244353;
int vis[10000000], isprim[10000000], lens, num = 1e7 - 5;
ll n, m;
template<const int T>
struct ModInt {
    const static int mod = T;
    int x;
    ModInt(int x = 0) : x(x % mod) {}
    int val() { return x; }
    ModInt operator + (const ModInt &a) const { int x0 = x + a.x; return ModInt(x0 < mod ? x0 : x0 - mod); }
    ModInt operator - (const ModInt &a) const { int x0 = x - a.x; return ModInt(x0 < mod ? x0 + mod : x0); }
    ModInt operator * (const ModInt &a) const { return ModInt(1LL * x * a.x % mod); }
    ModInt operator / (const ModInt &a) const { return *this * a.inv(); }
    void operator += (const ModInt &a) { x += a.x; if (x >= mod) x -= mod; }
    void operator -= (const ModInt &a) { x -= a.x; if (x < 0) x += mod; }
    void operator *= (const ModInt &a) { x = 1LL * x * a.x % mod; }
    void operator /= (const ModInt &a) { *this = *this / a; }
    friend ostream &operator<<(ostream &os, const ModInt &a) { return os << a.x;}

    ModInt pow(int64_t n) const {
        ModInt res(1), mul(x);
        while(n){
            if (n & 1) res *= mul;
            mul *= mul;
            n >>= 1;
        }
        return res;
    }

    ModInt inv() const {
        int a = x, b = mod, u = 1, v = 0;
        while (b) {
            int t = a / b;
            a -= t * b; swap(a, b);
            u -= t * v; swap(u, v);
        }
        if (u < 0) u += mod;
        return u;
    }

};
typedef ModInt<mod> mint;

void prim() {
    for(int i = 2; i <= num; i++)
    {
    	if(vis[i] == 0)
    	isprim[++lens] = i;
    	for( int j = 1; j <= lens && i * isprim[j] <= num; j++)
    	{
    		vis[i*isprim[j]]=1;
    		if(i % isprim[j] == 0)
    		break;
		}
	}
}

int main() {
	prim();
	scanf("%lld%lld", &n, &m);
	mint ans = 0, poww = 1, res = 0, mul = 1;
	ll lcm = 1;
	for( int i = 1; i <= n; i++) {
		poww *= mint(m % mod);
		ans += poww;
	}
	for( int i = 1; i <= n; i++) {
		if(!vis[i]) lcm *= i;
		if(lcm > m) break;
		mul *= mint(m / lcm % mod);
		res += mul;
	}
	cout << ans - res;
}

#include <bits/stdc++.h>

using namespace std;

#define all(a) (a).begin(), (a).end()
typedef long long int ll;

ll MOD = 998244353;
ll maxN = 3 * 100000;

bool isPrime(int n) {
    for (ll i = 2; i * i <= n; i++) {
        if (n % i == 0) return false;
    }
    return true;
}

void solve(int tc) {
    ll n, m;
    cin >> n >> m;
    vector<ll> a(n + 1);
    a[0] = 1;
    ll ans = 0;
    for (ll i = 1; i <= n; i++) {
        a[i] = a[i - 1] * (m % MOD);
        a[i] %= MOD;
        ans += a[i];
        ans %= MOD;
    }
    ll p = 1, cnt = 1;
    for (int i = 1; i <= n; i++) {
        if (p > m) break;
        if (isPrime(i)) p *= i;
        cnt *= (m / p) % MOD;
        cnt %= MOD;
        ans = (ans - cnt + MOD) % MOD;
    }
    cout << ans << endl;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif

    int t = 1;
    // cin >> t;

    for (int tc = 1; tc < t + 1; tc++) {
        solve(tc);
    }
}

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
const int mod=998244353;
typedef long long LL;
const int N=3e5+10;
int isp[N];
LL n,m,res=0;
int main(){
    ios::sync_with_stdio(false); cin.tie(0);
    cin>>n>>m;
    for(int i=2;i<=n;i++){
        for(int j=2*i;j<=n;j+=i){
            isp[j]=1;
        }
    }

    LL num=m%mod,res=0,unambious=m%mod,t=m%mod,f=1;
    /* num 前一列的数量
    unambious 走到前一列可以继续满足不模糊的个数
    t 1-m中 可以满足继续不模糊的个数
    */
    for(int i=2;i<=n;i++){
        if(!isp[i]){
            f=f*i;
        }
        t=m/f;

        res=(res+m%mod*num)%mod;
        res=(res-t%mod*unambious)%mod;

        num=(m%mod*num)%mod;
        unambious=(t%mod*unambious)%mod;
    }

    cout<<(res+mod)%mod<<endl;
}

#include <algorithm>
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 5e5 + 10;
const int mod = 998244353;
#define ll __int128
int n, m;
bool is_prime[N + 1]; // default true
ll a[N];
vector<int> prime;
ll mul[N];
void init() {
    memset(is_prime, true, sizeof(is_prime));
    is_prime[0] = is_prime[1] = false;
    for (int i = 2; i < N; ++i) {
        if (is_prime[i])
            prime.push_back(i);
        for (auto j : prime) {
            if (i * j > N)
                break;
            is_prime[i * j] = false;
            if (i % j == 0)
                break;
        }
    }
    mul[0] = 1;
    for (int i = 1; i <= prime.size(); ++i) {
        mul[i] = mul[i - 1] * prime[i - 1];
        if (mul[i] > m)
            mul[i] = m + 1;
    }
}
ll get(int i) {
    int pos = upper_bound(prime.begin(), prime.end(), i) - prime.begin();
    // cout << pos << endl;
    ll x = mul[pos];
    // cout << x << endl;
    return (m / x) % mod;
}
signed main() {
    cin >> n >> m;
    init();
    ll no_ambious = m;
    ll sum = m;
    ll sum_no_ambious = 0;
    ll ssum = 0;
    for (int i = 2; i <= n; ++i) {
        no_ambious = no_ambious * get(i) % mod;
      //  cout << i << " " << no_ambious << endl;
        sum = sum * (m % mod) % mod;
        ssum = (ssum + sum) % mod;
        sum_no_ambious = (sum_no_ambious + no_ambious) % mod;
    }
    int ans = (ssum - sum_no_ambious + mod) % mod;
    cout << ans << "\n";
}

#include<bits/stdc++.h>
using namespace std;
const long long N = 998244353;
long long Mod(long long x ,long long y){
	x %= N;
	long long da = 1;
	while(y){
		if(y % 2 == 0)x = (x * x) % N,y /= 2;
		else da = (da * x) % N,y--;
	}
	return da % N;
}
int main(){
	std::ios::sync_with_stdio(false);
 	cin.tie(0);
 	cout.tie(0);
	long long n,m;

	cin>>n>>m;
	long long da = 0;
	for(int i = 2;i <= n;i++) da = (da + Mod(m,i)) % N;
	long long tmp = 0,cnt = m;
	for(long long i = 2;i <= n;i++){
		if(tmp == 0) tmp = i;
		else if(__gcd(tmp,i) == 1){
			if(tmp <= m / i)tmp *= i;
			else break;
		}
		cnt = ((cnt % N ) * ((m / tmp) % N)) % N;
		da = (da - cnt % N + N) % N;

	}
	cout<<da<<endl;
	return 0;
}

#include <bits/stdc++.h>

using namespace std;
using ll = long long;
using P = pair <int, int>;

template <typename T>
inline void read(T &x) {
    x = 0; char c = getchar();
    int f = 0;
    for (; !isdigit(c); c = getchar()) f |= c == '-';
    for (; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
    if (f) x = -x;
}

template <typename T, typename ...Args>
inline void read(T &x, Args &...args) {
    read(x), read(args...);
}
template <typename T>
inline void write(T x, char ch) {
    if (x < 0) x = -x, putchar('-');
    static short st[70], tp;
    do st[++tp] = x % 10, x /= 10; while (x);
    while (tp) putchar(st[tp--] | 48);
    putchar(ch);
}

template <typename T, typename ...Args>
inline void write(T x, char ch, Args ...args) {
    write(x, ch), write(args...);
}

#define Fr(i,l,r) for (int i = (l); i <= (r); ++i)
#define Rf(i,r,l) for (int i = (r); i >= (l); --i)

const int N = 3e5 + 5, mod = 998244353;

bool st[N];

ll n, m;

signed main() {
    // freopen("1.out", "w", stdout);
    read(n, m);
    for (int i = 2; i <= n; ++i) {
        for (int j = i + i; j <= n; j += i) {
            st[j] = 1;
        }
    }
    ll hh = 0;
    ll ans = 1;
    ll cur = 1;
    ll sum = 1;
    Fr (i, 1, n) {
        if (cur <= m) if (!st[i]) cur *= i;
        ans = ans * ((m / cur) % mod) % mod;
        sum = sum * (m % mod) % mod;
        // write(ans, ' ', sum, '\n');
        hh = (hh + (sum + mod - ans) % mod) % mod;
    }
    write(hh, '\n');
    return 0;
}

// LUOGU_RID: 93988294
#include<bits/stdc++.h>
using namespace std;
#define pr pair<ll,ll>
#define mp make_pair
#define _(x,y) x=(x+y)%mod
#define ll long long
	#define int long long
int read(){int d=1,k=0;char c=getchar();
while(!(c>='0' and c<='9' or c=='-'))c=getchar();if(c=='-')d=-1,c=getchar();
while(c>='0' and c<='9')k=(k<<3)+(k<<1)+(c^48),c=getchar();return d*k;}

const int lim=4e5,mod=998244353;
int dp[1000000][2],pd[1000000];

signed main(){

	pd[1]=1;for(int i=2;i<=lim;i++){
		if(pd[i])continue;
		for(int j=2;j*i<=lim;j++)pd[i*j]=1;
	}
	int n=read(),m=read();
	int ans=0;
	dp[1][0]=m%mod;
	int lcm=1;
	bool flag=false;
	for(int i=2;i<=n;i++){
		if(!flag){
			if(!pd[i])lcm*=i;
			if(lcm>m)flag=true;
		}
		int canuse=m/lcm;
		dp[i][0]=dp[i-1][0]*(canuse%mod)%mod;
		dp[i][1]=(dp[i-1][1]*(m%mod)%mod+dp[i-1][0]*((m-canuse)%mod)%mod)%mod;
		_(ans,dp[i][1]);
	}cout<<ans;

	return 0;
}

#include <bits/stdc++.h>
using namespace std;

// Macros
#define ll long long
#define vb vector<bool>
#define vl vector<long long>
#define vvl vector<vector<long long>>
#define vpl vector<pair<long long, long long>>
#define ml map<long long, long long>
#define mpl map<pair<long long, long>, pair<long long, long long>>
#define pl pair<long long, long long>
#define all(x) x.begin(), x.end()
#define sortall(x) sort(x.begin(), x.end())
#define ff first
#define ss second
#define pb push_back
#define mp make_pair
#define pb push_back
#define vi vector<ll>
#define pi pair<ll, ll>
#define nl cout << "\n";
#define rep(i, a, b) for (ll i = a; i < b; i++)
#define rrep(i, a, b) for (ll i = a; i > b; i--)
#define bharo(arr, n)          \
    for (ll i = 0; i < n; i++) \
    {                          \
        cin >> arr[i];         \
    }
#define dikhao(arr, n)         \
    for (ll i = 0; i < n; i++) \
    {                          \
        cout << arr[i] << " "; \
    }

// Constants
const long long M = 998244353;
const long long llmax = LONG_LONG_MAX;
const string yes = "YES";
const string no = "NO";

const ll SIZE = 26;

struct TrieNode
{
    struct TrieNode *children[SIZE];
    bool isEndOfWord;
};

unsigned long long power(unsigned long long x,
                         ll y, ll p)
{
    unsigned long long res = 1; // Initialize result

    x = x % p; // Update x if it is more than or
    // equal to p
    while (y > 0)
    {

        // If y is odd, multiply x with result
        if (y & 1)
            res = (res * x) % p;

        // y must be even now
        y = y >> 1; // y = y/2
        x = (x * x) % p;
    }
    return res;
}

unsigned long long powerr(unsigned long long x,
                          ll y, ll p)
{
    unsigned long long res = 1; // Initialize result

    x = x % p; // Update x if it is more than or
    // equal to p
    if (x == 0)
        return 0;
    while (y > 0)
    {

        // If y is odd, multiply x with result
        if (y & 1)
            res = (res * x) % p;

        // y must be even now
        y = y >> 1; // y = y/2
        x = (x * x) % p;
    }
    return res;
}
const ll N = 1e5;
bool arr[3 * N + 1];
ll countt[3 * N + 1];

void SieveOfEratosthenes(ll n)
{
    for (ll i = 0; i <= n; i++)
    {
        arr[i] = true;
        countt[i] = 0;
    }
    // Create a boolean array "prime[0..n]" and initialize
    // all entries it as true. A value in prime[i] will
    // finally be false if i is Not a prime, else true.
    for (ll p = 2; p * p <= n; p++)
    {
        ll c = 0;
        // If prime[p] is not changed, then it is a prime
        if (arr[p] == true)
        {
            // Update all multiples of p greater than or
            // equal to the square of it numbers which are
            // multiple of p and are less than p^2 are
            // already been marked.
            for (ll i = p * p; i <= n; i += p)
            {
                if (arr[i] == true)
                    c++;
                arr[i] = false;
            }
        }
        countt[p] = c;
    }

    // Prll all prime numbers
}

ll modInverse(ll A, ll M)
{
    ll m0 = M;
    ll y = 0, x = 1;

    if (M == 1)
        return 0;

    while (A > 1)
    {
        // q is quotient
        ll q = A / M;
        ll t = M;

        // m is remainder now, process same as
        // Euclid's algo
        M = A % M, A = t;
        t = y;

        // Update y and x
        y = x - q * y;
        x = t;
    }

    // Make x positive
    if (x < 0)
        x += m0;

    return x;
}

int main()
{
    ll t;
    t = 1;
    // cin>>t;
    while (t--)
    {
        ll n;
        cin >> n;
        ll m;
        cin >> m;
        ll temp = m;
        ll ans = m;
        // ll num2 = 1;
        ll sum1 = 0;
        SieveOfEratosthenes(n);
        rep(i, 2, n + 1)
        {
            if (arr[i] == true)
            {
                // num2 *= i;
                // m = temp / num2;
                m /= i;
            }
            ans = (ans % M) * (m % M);
            ans = ans % M;
            sum1 = sum1 + ans;
            sum1 %= M;
        }
        ll sum = 0;
        sum = (powerr(temp, 2, M) * ((powerr(temp, n - 1, M) - 1) % M)) % M;
        sum = (sum * (modInverse(temp - 1, M))) % M;
        sum -= sum1;
        sum += M;
        sum = (sum + M) % M;
        if (temp != 1)
            cout << sum << "\n";
        else
            cout << n - 1 << "\n";
    }
    return 0;
}

#include <bits/stdc++.h>

#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-O3")
#pragma GCC target("avx2")

using namespace std;

#define pb push_back
#define sz size()
#define all(x) x.begin(), x.end()
#define F first
#define S second
#define int long long

typedef pair < int, int > pii;
typedef vector < int >  vi;
typedef vector < vi >  vvi;

const int N = 300300, mod = 998244353, maxA = 1e12;
vvi del(N);
int prod[N], val[N], prime[N];

int bp (int x, int st) {
    if (st == 0) {
        return 1;
    }
    int t = bp(x, st / 2);
    t *= t;
    t %= mod;
    if (st & 1) {
        t *= x;
    }
    return t % mod;
}

void solve(){
    int n, m;
    cin >> n >> m;

    int st[n + 10];
    st[0] = 1;

    int fact = 1;
    for (int i = 1; i <= n; i++) {
        st[i] = st[i - 1];
        st[i] *= m % mod;
        st[i] %= mod;
        if (fact <= m && prime[i])
            fact *= i;
        val[i] = m / fact;
    }

    int ans = 0;
    vi dp(n + 7, 0);
    dp[0] = 1;
    for (int i = 1; i <= n; i++) {
        dp[i] = dp[i - 1] * (val[i] % mod);
        dp[i] %= mod;
        ans += st[i] - dp[i];
        ans += mod;
        ans %= mod;
    }
    cout << ans;
}

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);

    for (int i = 2; i < N; i++) {
        int f = 1;
        for (int j = 2; j * j <= i; j++) {
            if (i % j == 0) {
                f = 0;
                break;
            }
        }
        prime[i] = f;
    }

    int t = 1;
    //cin >> t;
    while (t--) {
        solve();
        cout << "\n";
    }
}

// Problem: D. Counting Arrays
// Contest: Codeforces - Educational Codeforces Round 138 (Rated for Div. 2)
// URL: https://codeforces.com/contest/1749/problem/D
// Memory Limit: 512 MB
// Time Limit: 2000 ms

#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>

using namespace std;
using namespace __gnu_pbds;

#ifndef ONLINE_JUDGE
   #define now(x) cout<<#x<<" : "<<x<<'\n'; //" on line : "<<__LINE__<<'\n';
   #define pm(m)  cout<<#m<<" : "; for(auto it:m) cout<<it.fs<<" "<<it.ss<<'\n';
   #define fv(v)  cout<<#v<<" : "; for(auto it:v) cout<<it<<" "; cout<<'\n';
#else
   #define now(x) ;
   #define fv(v) ;
   #define pm(m) ;
#endif

template<typename T>
istream& operator >>(istream& istream, vector<T>& v) {
    for(auto &it : v) {
        cin >> it;
    }
    return istream;
}

template<typename T>
ostream& operator <<(ostream& ostream, vector<T>& v) {
    for(auto &it : v) {
        cout << it << " ";
    }
    return ostream;
}

const int mod = 998244353;
const double pi = 3.1415926536;
const long long oo=1e18;
#define FOR(i,z,n) for(int i=z;i<n;i++)
#define f(n) for(int i=0;i<n;i++)
#define int ll
typedef long long ll;
typedef  map<int,int> mii;
typedef  vector<int> vi;
#define fs first
#define ss second
#define itf(v) v.begin(),v.end()
#define itr(v) v.rbegin(),v.rend()
int modu(int a,int b=mod) 	{return (a%b+b)%b;}
int log2(int x){return __builtin_clzll(1LL) - __builtin_clzll(x);}
template<typename T> T maxxx() {return numeric_limits<T>::max();}
const int maxx=maxxx<int>();

// pbds
typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> ordered_set;
template <typename T> using ordered_mset = tree<T, null_type, less_equal<T>, rb_tree_tag, tree_order_statistics_node_update>;

// find_by_order(K): Returns an iterator to the Kth largest element (counting from zero)
// order_of_key (K): Returns the number of items that are strictly smaller than K
//less_equal -> multisets

/* ---------------TEMPLATE ENDS HERE-------------*/

int dx[]={-1,0,1,0};
int dy[]={0,1,0,-1};

const int sieve_counter=1e6;
vector<bool> prime(sieve_counter+1,1);
vector<int> primes;

void sieve()
{

    prime[0]=prime[1]=0;
    int i;
    for( i=2;i*i<=sieve_counter;i++)
    {
        if(prime[i]) //1 means prime 0 means composite
        {
            primes.push_back(i);
            for(int j=i*i;j<=sieve_counter;j+=i)
            {
                prime[j]=0;
            }
        }
    }

    for(i;i<=sieve_counter;i++)
    {
        if(prime[i])
        {
            primes.push_back(i);
        }
    }

    //cout<<primes.size()<<'\n';

}

int power(int a,int n,int mod)
{
  //binary exponentiation
  int res=1;
  a%=mod;
  while(n)
  {
      if(n&1) res=(res*a)%mod;
      n=n>>1;
      a=(a*a)%mod;

  }
    return res;

}
int fermat(int a,int p)
{
    return power(a,p-2,p);
}

void solve()
{
       int n=0,m=0,k=0,x=0,count=0,sum=0,ans=0;
       cin>>n>>m;

       ans = 1;
       int val = 1;
       int total = 0;
       if(m==1) total = n;
       else{
       	//all length from 1 till n
       	//GP -> m+m^2+m^3+...m^n

       	x = (m%mod * (power(m,n,mod)-1)%mod)%mod;
       	k = fermat(m-1,mod);
       	total = (x*k)%mod;
       }

       for(int i=1;i<=n;i++)
       {
       	if(prime[i])
       	{
       		val = (val*i);
       	}
       	//if(val>m) break;

       	int multiples = (m/val)%mod;
       	ans = (ans*multiples)%mod;
       	sum = (sum+ans)%mod;

       }
       sum = ((total-sum)%mod+mod)%mod;
       cout<<sum<<'\n';

}
int32_t main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	/*
	#ifndef ONLINE_JUDGE
		freopen("input.txt","r",stdin);
		freopen("output.txt","w",stdout);
	#endif
	*/
	sieve();
	 int test_case=1;
	//cin>>test_case;
	for(int _=0;_<test_case;_++)
	{	//cout<<"Case #"<<_+1<<": ";
		solve();
	}
	return 0;

}

#include<bits/stdc++.h>
#define int long long
#define endl "\n"
#define INF 0x3f3f3f3f3f3f3f3f
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
const int N=1e6;
const int MOD =998244353;
int prime[N+5];
bool vis[N+5];
int n,m;
void init(){
    for(int i=2;i<=N;i++){
    	if(!vis[i]){
    		prime[++prime[0]]=i;
		}
	    for(int j=1;j<=prime[0]&&i*prime[j]<=N;j++){
			vis[prime[j]*i]=true;
			if(i%prime[j]==0) break;
		}
	}
}
int ksm(int a,int x){
    int ans=1;
    while(x){
        if(x&1) ans=ans*a%MOD;
        a=a*a%MOD;
        x>>=1;
    }
    return ans;
}
void solve(){
  int64_t n, m;
  cin >> n >> m;
  int64_t ans = 0, mm = m % MOD;
  int64_t p = mm, cur = mm;
  vector<int> vis(n + 1);
  for (int64_t i = 2; i <= n; i++) {
    if (!vis[i]) {
      for (int j = i + i; j <= n; j += i) {
        vis[j] = 1;
      }
      m /= i;
    }
    int pw =(ksm(mm,i)) % MOD;
    cur = (cur * (m % MOD)) % MOD;
    ans = ans + (pw - cur) % MOD;
  }
  cout << (ans % MOD + MOD) % MOD << "\n";
}
signed main(){
	IOS;
	init();
    solve();
}

#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
int mod = 998244353;
ll add(ll x, ll y) {
	x += y;
	if (x >= mod)x -= mod;
	if (x < 0)x += mod;
	return x;
}
ll sub(ll x, ll y) {
	return add(x, -y);
}
ll mul(ll x, ll y) {
	return (x * y % mod);
}
ll binpow(ll x, int y) {
	ll res = 1;
	for (; y; y >>= 1,x = mul(x, x)) {
		if (y & 1)res = mul(res, x);
	}
	return res;
}
bool isprime(int x) {
	int k = sqrt(x);
	for (int i = 2; i <= k; i++) {
		if (x % i == 0)return false;
	}
	return true;
}
int main() {
	ios::sync_with_stdio(false), cin.tie(0);
	int n;
	ll m;
	cin >> n >> m;
	ll ans=0;
	for (int i = 1; i <= n; i++) {
		ans = add(ans, binpow(m % mod, i));
	}
	ll cur = 1,cnt=1;
	for (int i = 1; i <= n; i++) {
		if (cur > m)break;;
		if (isprime(i))cur *= i;
		cnt = mul(cnt, (m/cur)%mod);
		ans = sub(ans, cnt);
	}
	cout << ans;
}

#include <map>
#include <iostream>
#include <random>
using namespace std;
#include <vector>
#include <queue>
#include <set>
#include <algorithm>
#define ll long long
#define vi vector<int>
#define vll vector<ll>
#define pi pair<int,int>
#define pll pair<ll,ll>
#define vb vector<bool>
#include <string>
#include <cassert>
#pragma warning(disable : 4996)
#define stop return stopi()
void stopi() {
    cout << "NO" << "\n";
}
void yes() {
    cout << "YES" << "\n";
}
const ll mod = 998244353;
void solve() {
    ll n,m;
    cin >> n >> m;
    const ll siz = 3e5+1;
    vb arto(siz);
    vll mul(siz);
    mul[1] = 1;
    for (ll i = 2; i < siz; i++) {
        if (!arto[i]) {
            for (ll j = 0; j * i < siz; j++) {
                arto[i * j] = 1;
            }
            if (mul[i - 1] > m) {
                mul[i] = mul[i - 1];
            }
            else {
                mul[i] = mul[i - 1] * i;
            }
        }
        else {
            mul[i] = mul[i - 1];
        }
    }
    ll ans = 0;
    ll s = 1;
    ll sum = 0;
    ll momo = m % mod;
    ll mu = momo;
    for (int i = 1; i <= n; i++) {
        sum += mu;
        mu = (mu * momo) % mod;
        ll d = m / mul[i];
        d %= mod;
        s = (s * d)%mod;
        ans += s;
        ans %= mod;
        sum %= mod;
    }
    if (sum - ans < 0) {
        sum += mod;
    }
    cout << sum - ans;

}
int main()
{
    int t=1;
    //cin >> t;
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    for (int i = 0; i < t; i++) {
        solve();
    }
}

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define ll long long
#define Max 1000005
#define endl '\n'
#define PL pair<int,int>
const int mod = 998244353;
ll dp[Max];
int prime[Max];
bool vis[Max];
int cnt = 0;
void Era_prime(int n) {
    for (int i = 2; i <= n; i++) {
        if (vis[i]) {
            for (int j = i * 2; j <= n; j += i) {
                vis[j] = false;
            }
        }
    }
}
void solve() {
    ll n, m, t;
    cin >> n >> m;
    t = m;
    for (int i = 1; i <= n; i++) {
        vis[i] = 1;
    }
    Era_prime(n);
    ll ans = 1, sum = 0, op = 1, cao = 0, gg = 1;
    for (int i = 1; i <= n; i++) {
        op = op * (m % mod) % mod;
        cao = (cao + op ) % mod;
    }
    op=1;
    for (int i = 1; i <= n; i++) {
        if (vis[i])gg = gg * i;
        if (gg > m) {
            break;
        }
        ans=m/gg%mod*ans%mod;
        cao=(cao-ans+mod)%mod;
    }
    cout << cao << endl;
}
signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cout << fixed << setprecision(12);
    int t = 1;    //cin >> t;
    while (t--) {
        solve();
    }
}

// Hydro submission #6375f4cee44d9611eaab12be@1668674766692
#include <iostream>
using namespace std;

#define int long long
const int N=3e5+100,mod=998244353;
int n,m;
int cnt[N];
int ans;
int a;
int isprime[N],prime[N],cntt;
int qq=1;
int realans;
int f[N];

signed main(){
	cin>>n>>m;
	for(int i=2;i<=n;++i)
		cnt[i]=m/i;
	isprime[1]=1;
	for(int i=2;i<=n;++i){
		if(isprime[i]==0){
			for(int j=2;j*i<=n;++j)
				isprime[i*j]=1;
		}
	}
//	cout<<cntt<<endl;
//	m=mod;
	f[1]=m%mod;
	//g[1]=1;
	int qwq=1;
	ans=m%mod;
	for(int i=2;i<=n;++i){
	//	qq=qq*m%mod;
		if(isprime[i]==0){
			qwq=(qwq*i);//算的是 有
			if(qwq>m)
				qwq=m+1;
		}
        f[i]=f[i-1]*((m/qwq)%mod)%mod;
		//ans=ans*((m-qwq+mod)%mod)%mod;//好的

        ans=ans*(m%mod)%mod;
	//	cout<<i<<":"<<" "<<qwq<<" "<<ans<<endl;
        realans=(realans+ans-f[i]+mod)%mod;
	//	if(i==1);
	//		//qwq++;
	//	else
	//		realans=(realans+qq-ans+mod)%mod;
	}
//	cout<<ans<<endl;
	//cout<<(qq-ans+mod)%mod<<endl;
	cout<<realans<<endl;
	return 0;
}

// #include<bits/stdc++.h>
// using namespace std;
// #define ll long long
// ll mod = 998244353;

// ll power(ll a, ll b){
//     if(b==0) return 1;
//     if(b==1) return a;
//     ll x = power(a, b/2) % mod;
//     if(b % 2 == 0) return (x * x) % mod;
//     return (((x * x) % mod) * (a % mod)) % mod;
// }

// ll find_total(ll m, ll n){
//     ll num = m % mod;
//     ll p = power(m, n) % mod;
//     p = (p - 1 + mod) % mod;
//     num = (num * p) % mod;

//     ll den = m - 1;
//     ll den_mod = power(den, mod - 2) % mod;
//     ll res = ((num % mod) * (den_mod % mod)) % mod;
//     return res % mod;
// }

// ll isPrime(ll x){
//     if(x<2) return 0;
//     for(ll i=2; i*i <= x; i++){
//         if(x%i==0) return 0;
//     }
//     return 1;
// }

// int main(){
//     int t;
//     // cin >> t;
//     t = 1;
//     while(t--){
//         ll n, m;
//         cin >> n >> m;
//         // ll total = find_total(m, n);
//         // ll ambi = find_ambi(m, n);
//         // cout << (total - ambi + mod) % mod << "\n";
//         ll total = find_total(m, n);
//         ll prod_of_primes = 1;
//         ll prod = 1;
//         for(ll i=1; i<=n; i++){
//             if(prod_of_primes > m) continue;
//             if(isPrime(i)) prod_of_primes *= i;
//             prod = (prod * ((m / prod_of_primes) % mod)) % mod;
//             total = (total - prod + mod) % mod;
//         }
//         cout << total << "\n";
//     }
//     return 0;
// }

#include <bits/stdc++.h>

using namespace std;

const int MOD = 998244353;

int add(int x, int y)
{
    x += y;
    while(x >= MOD) x -= MOD;
    while(x < 0) x += MOD;
    return x;
}

int sub(int x, int y)
{
    return add(x, -y);
}

int mul(int x, int y)
{
    return (x * 1ll * y) % MOD;
}

int binpow(int x, int y)
{
    int z = 1;
    while(y)
    {
        if(y & 1) z = mul(z, x);
        x = mul(x, x);
        y >>= 1;
    }
    return z;
}

bool prime(int x)
{
    for(int i = 2; i * 1ll * i <= x; i++)
        if(x % i == 0)
            return false;
    return true;
}

int main()
{
    int n;
    long long m;
    cin >> n >> m;
    int ans = 0;
    for(int i = 1; i <= n; i++)
        ans = add(ans, binpow(m % MOD, i));
    long long cur = 1;
    int cnt = 1;
    for(int i = 1; i <= n; i++)
    {
        if(cur > m) continue;
        if(prime(i)) cur *= i;
        cnt = mul(cnt, (m / cur) % MOD);
        ans = sub(ans, cnt);
    }
    cout << ans << endl;
}

#include <bits/stdc++.h>
#pragma GCC optimize("O3")
#pragma GCC optimize("-Ofast", "-funroll-all-loops", "-ffast-math")
#pragma GCC target("avx2,fma")
#pragma GCC optimize("unroll-loops")
using namespace std;
#define IOS ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define bug system("pause")
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int inf = 0x3f3f3f3f;
const ll lnf = 0x7f7f7f7f7f7f7f7f;
const double eps = 1e-6;
const double pi = acos(-1.0);
const int mod = 998244353;
const int N = 1e6 + 10;
const int M = 1e7 + 10;

ll n, m;
ll power(ll a, ll b)
{
    a %= mod;
    ll ans = 1;
    for (; b; b >>= 1, a = a * a % mod)
        if (b & 1)
            ans = ans * a % mod;
    return ans;
}

int main()
{
    IOS;
    cin >> n >> m;
    ll ans = 0, tmp = m % mod, x = 0;
    for (int i = 2; i <= n; i++)
        ans = (ans + power(m, i)) % mod;
    for (ll i = 2; i <= n; i++)
    {
        if (!x)
            x = i;
        else if (__gcd(x, i) == 1)
        {
            if (x <= m / i)
                x *= i;
            else
                break;
        }
        tmp = tmp * ((m / x) % mod) % mod;
        ans = (ans - tmp + mod) % mod;
    }
    cout << ans;
    return 0;
}

#include<bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define db double
#define int long long
#define PII air<int,int >
#define mem(a,b) memset(a,b,sizeof(a))
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);

using namespace std;
const int mod = 998244353,inf = 1e18;
const int N = 3e5+10,M = 2010;

int T,n,m,k;
int va[N];
int pri[N],st[N],cnt;

void init(int x)
{
	for(int i=2;i<=x;i++)
	{
		if(!st[i]) pri[++cnt] = i;
		for(int j=1;pri[j]*i<=n;j++)
		{
			st[pri[j]*i] = 1;
			if(i%pri[j]==0) break;
		}
	}
}

__int128 ksm(__int128 a,__int128 b)
{
	__int128 sum = 1;
	while(b)
	{
		if(b&1) sum = sum*a%mod;
		a = a*a%mod;
		b >>= 1;
	}
	return sum;
}

void print(__int128 x)
{
    if(x<0){putchar('-');x = -x;}
    if (x/10) print(x / 10);
    putchar(x % 10 + '0');
}

signed main()
{
	IOS;
	long long x,y;cin>>x>>y;
	n = x,m = y;
	init(n);
	__int128 ans = 0;
	for(int i=1;i<=n;i++) ans = (ans+ksm(m,i))%mod;
	__int128 pre = 1,res = 1,r = 0;
	for(int i=1;i<=n;i++)
	{
		while(pri[r+1]<=i&&r+1<=cnt)
		{
			res *= pri[++r];
			if(res>m) break;
		}
		if(res>m) break;
		pre = pre*(m/res)%mod;
		ans = (ans-pre)%mod;
	}
	ans = (ans%mod+mod)%mod;
	print(ans);
	return 0;
}

#include<cstdio>
#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
#define ll long long
#define lowbit(x) x&(-x)
#define endl '\n'
#define wk is zqx ta die
const ll mod = 998244353;
ll s[300005];
ll add(ll a, ll b) {
	ll res = 0;
	while (b) {
		if (b & 1) {
			res = res + a;
			res %= mod;
		}
		a = a + a;
		a %= mod;
		b >>= 1;
	}
	return res;
}
ll pow(ll a, ll b) {
	ll res = 1;
	while (b) {
		if (b & 1) {
			res = add(res, a);
		}
		a = add(a, a);
		b >>= 1;
	}
	return res;
}
bool ispri[300005];
int main() {
	std::ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	//	for (int i = 2; i <= 300000; i++) {
	//		for (int j = i; j <= 300000; j += i) {
	//			phi[j]++;
	//		}
	//	}
	for (int i = 2; i <= 300000; i++) {
		if (ispri[i] == 0) {
			for (int j = i + i; j <= 300000; j += i) {
				ispri[j] = 1;
			}
		}
	}
	ll n, m;
	cin >> n >> m;
	ll sum = 1;
	for (int i = 2; i <= n; i++) {
		if (ispri[i] == 0) {
			sum = sum * i;
			if (sum > m) {
				break;
			}
		}
		s[i] = m / sum;
	}
	for (int i = 3; i <= n; i++) {
		s[i] = add(s[i], s[i - 1]);
		//		cout << s[i] << endl;
	}
	ll ans = 0;
	ll mo = m % mod;
//	ans = (pow(m, n + 1) - 2 - mo + mod) % mod;
//	cout << ans << endl;
	ll cnt = add(m, m);
	for (int i = 2; i <= n; i++) {
		ans = ans + cnt;
		ans %= mod;
		cnt = add(cnt, m);
	}
	for (int i = 2; i <= n; i++) {
		ans = ans - add(s[i], m);
		ans = (ans + mod) % mod;
	}
	cout << ans << endl;
	return 0;
}

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int Mod=998244353;
int t,n,m,sum,num;
int ksm(int x,int y)
{
	int ret=1,bace=x;
	while(y)
	{
		if(y&1)ret=(ret*bace)%Mod;
		bace=(bace*bace)%Mod;
		y>>=1;
	}
	return ret;
}
int cal(int x,int y)
{
	for(int i=2;i<=y;i++)
	    while(!(y%i))
		{
			if(x%i)x*=i;
	    	y/=i;
	    	num++;
		}
	return x;
}
signed main()
{
	scanf("%lld%lld",&n,&m);
	int x=m%Mod,qmr=1,ans=m%Mod;
	if(m>1)sum=(ksm(m%Mod,n+1)-(m%Mod)+Mod)%Mod*ksm((m-1)%Mod,Mod-2)%Mod;
	else sum=n;
	for(int i=2;i<=n;i++)
	{
		qmr=cal(qmr,i);
		if(qmr>m)break;
		else
		{
			x*=((m/qmr)%Mod);
			x%=Mod;
			ans=(ans+x)%Mod;
		}
	}
	printf("%lld\n",(sum-ans+Mod)%Mod);
	return 0;
}

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

#define fastio ios_base::sync_with_stdio(false);cin.tie(NULL)
#define testcase int T; cin >> T; for (int tc = 1; tc <= T; tc++)
#define MAX 1000000007
#define Limit 1000000000
#define modulo 998244353
#define INF 4000000000000000005
#define vi vector<int>
#define vl vector<long long>
#define vpi vector<pair<int,int> >
#define vpl vector<pair<long long,long long> >
#define pi pair<int,int>
#define pl pair<long long,long long>
#define ti tuple<int,int,int>
#define tiiii tuple<int,int,int,int>
#define tllb tuple<long long,long long,bool>
#define tl tuple<long long,long long,long long>
#define PI 2*acos(0.0)
#define pb push_back
#define mkp make_pair
#define endl '\n'

const double threshold = (1.0/1000000.0);
const int nmax = 1e5+5;

ll primes[13] = {2,3,5,7,11,13,17,19,23,29,31,37,41};

ll n,m;

int main()
{
    fastio;

    cin>>n>>m;

    ll lim = m;

    m%=modulo;

    ll primePtr = 0, mul=m, ans = m, primeMul=1, res=0;

    bool flag = true;

    for(ll i=2;i<=n;i++)
    {

        mul *= m; mul%=modulo;

        if(primeMul<=lim && i>=primes[primePtr])
        {
            primeMul*=primes[primePtr];
            primePtr++;
            //cout<<primes[primePtr]<<" ";
        }

        if(primeMul > lim)
        {
            flag=false;
        }

        if(flag==true)
        {
            ans *= ((lim/primeMul)%modulo);

            ans%=modulo;

            res += ((((mul-ans)%modulo)+modulo)%modulo); res%=modulo;
        }
        else
        {
            res += mul; res %= modulo;
        }

        //cout<<res<<endl;
    }
    //cout<<endl;

    //cout<<mul<<" "<<ans<<endl;

    cout<<res<<endl;

    return 0;
}

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define TestCases int totalLTC ; cin >> totalLTC ; for(_case = 1 ; _case <=  totalLTC ; _case++)
#define FAST  ios_base::sync_with_stdio(0); cin.tie(NULL); cout.tie(NULL);
#define all(x)  (x).begin() , (x).end()
#define nl "\n"
int _case = 1 ;

int const MOD = 998244353  ;
const int N = 3e5 + 1e2;
vector<bool> is_prime(N+1, true);
void calculate()
{
    is_prime[0] = is_prime[1] = false;
    for (int i = 2; i * i <= N; i++)
    {
        if (is_prime[i])
        {
            for (int j = i * i; j <= N; j += i)
                is_prime[j] = false;
        }
    }
}

void solve()
{

    int ans = 0 ;

    int n , m ; cin >> n >> m ;

    int total = 1 ;
    int pr = 1 ;
    int curr = 1 ;

    for (int i = 1 ; i <= n; i++)
    {
        total *= (m%MOD) ;   total %= MOD ;

        if(is_prime[i])  curr *= i ;

        if(curr > m)
        {
            ans += total ; ans %= MOD ;
            continue;
        }

        int range = m / curr;
        range %= MOD;
        pr *= range ; pr %= MOD ;

        int x = (total - pr) ; if(x < 0) x += MOD ; x %= MOD ;
        ans += x ; ans %= MOD ;

    }

    cout << ans << nl ;

}
signed main(){   FAST  calculate() ;    solve() ;  }

// LUOGU_RID: 94225458
#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
const int N=300005;
const ll mod=998244353;
bool vis[N];
ll n,m,prime[N],tot=0,c[N],g[N];
void getprime(){
	memset(vis,1,sizeof(vis));
	for(int i=1;i<=n;i++)prime[i]=1;
	for(ll i=2;i<=n;i++){
		if(vis[i]){
			prime[i]=i;
			for(int j=i+i;j<=n;j+=i)vis[j]=0;
		}
	}
	g[1]=1;
	for(int i=2;i<=n;i++)g[i]=g[i-1]*prime[i];
//	for(int i=1;i<=n;i++)printf("%d ",g[i]);
}
int main(){
	cin>>n>>m;
	getprime();
	ll r1=1,r2=1;
	ll res=0;
	for(int i=1;i<=n;i++){
		if(g[i]>m)r1=0;
		else r1=(r1*((m/g[i])%mod))%mod;
		r2=(r2*(m%mod))%mod;
		res=(res+(r2-r1+mod)%mod+mod)%mod;
	}
	cout<<res<<endl;
	return 0;
}
//´æÔÚambiguous:´æÔÚÄ³¸öaiÓë2-iÖÐÄ³¸öÊý»¥ÖÊ
//²»´æÔÚambiguous£ºÃ¿Ò»¸öaiÓë2-iËùÓÐÊý²»»¥ÖÊ£¬¼´aiÊÇ2-iËùÓÐËØÊýµÄ¹«±¶Êý
//g[i]=2-iËùÓÐËØÊýµÄ³Ë»ý
//ÎªÁË±£Ö¤²»´æÔÚambiguous£¬aiµÄ¿ÉÄÜÊýÁ¿Îª£ºm/g[i]
//³¤¶ÈÎªnµÄÐòÁÐ£¬²»´æÔÚambiguousµÄÇé¿ö£º(m/g[i])µÄ³Ë»ý£¬i´Ó1µ½n£¬ÉèÎªr1
//³¤¶ÈÎªn£¬´æÔÚambiguousµÄÇé¿ö£ºmµÄn´Î·½-r1
//Çó³¤¶È1-nµÄÐòÁÐÖÐambiguousÊýÁ¿×ÜºÍ

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int, int>;
#define fi first
#define se second
#define mp make_pair
#define sz(x) int((x).size())
#define all(x) begin(x), end(x)

const ll mod = 998244353;

ll gcd(ll a, ll b) {
    if (b == 0) {
        return a;
    }
    if (a == 0) {
        return b;
    }
    return gcd(b, a % b);
}

bool is_prime(ll a) {
    for (int i = 2; i * i <= a; i++) {
        if ((a % i) == 0) {
            return false;
        }
    }
    return true;
}

int main() {
    cin.tie(0)->sync_with_stdio(0);
    ll n, m;
    cin >> n >> m;
    ll sol = 0, cur_exp = 1;
    for (int i = 1; i <= n; i++) {
        cur_exp = (cur_exp * (m % mod)) % mod;
        sol = (sol + cur_exp) % mod;
    }
    ll cur_not = 1, cur_prod = 1;
    for (int i = 1; i <= n; i++) {
        if (is_prime(i)) {
            cur_prod *= i;
            if (cur_prod > m) {
                break;
            }
        }
        cur_not = (cur_not * ((m / cur_prod) % mod)) % mod;
        sol = ((sol - cur_not) % mod + mod) % mod;
    }
    cout << sol << '\n';
}

#include<iostream>
#include<algorithm>
#include<queue>
#include<set>
#include<string>
#include<cstring>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
ll n, mod = 998244353, m,k,f[N],g[N],f2[N];
ll qpow(ll a, ll b=mod-2) {
	ll r = 1;
	while (b) {
		if (b & 1)r = r * a % mod;
		a = a * a % mod;
		b >>= 1;
	}return r;
}
ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a % b); }
bool prime(ll x) {
	for (int i = 2; i <x; i++) {
		if (x % i == 0)return 0;
	}
	return 1;
}
void solve() {
	cin >> n >> m;
	ll ans = 1;
	ll res = 0;
	for (int i = 1; i <= n; i++) {
		res += qpow(m%mod, i)%mod;
		res %= mod;
	}
	ll res2 = 0;
	ll u = 1;
	for (int i = 1; i <= n; i++) {
		if (prime(i))u = u * i;
		if (u > m)break;
		ans *= (m / u)%mod; ans %= mod;
		res2 +=ans ,res2%=mod;
	}
	cout << (res-res2+mod)%mod<< '\n';
}
int main() {
	int t = 1;
	//cin >> t;
	while (t--)solve();
	return 0;
}

// LUOGU_RID: 91772381
#include<stdio.h>
#include<iostream>
#include<cmath>
using namespace std;
int d[300001];
int f[300001];
const long long Mod = 998244353;
long long Pow(long long i, long long j);
int main(){
	int a;
	int b;
	long long c1, c2, c3;
	long long g1, g2, g3;
	long long n, m;
	int cnt;
	cnt = 1;
	scanf("%lld", &n);
	scanf("%lld", &m);
	g1 = 1;
	g2 = 1;
	g3 = 0;
	cnt = 0;
	for(c1 = 2;c1 <= n;c1++){
		if(f[c1] == 0){
			d[++cnt] = c1;
		}
		for(c2 = 1;c2 <= cnt;c2++){
			if(c1 * d[c2] > n){
				break;
			}
			f[c1 * d[c2]] = 1;
			if(c1 % d[c2] == 0){
				break;
			}
		}
	}
	for(c1 = 1;c1 <= n;c1++){
		if(g2 <= 1e12 && f[c1] == 0){
			g2 = g2 * c1;
		}
		g1 = (m / g2) % Mod * g1 % Mod;
		g3 = (((Pow(m, c1) - g1) % Mod + Mod) % Mod + g3) % Mod;
	}
	printf("%lld\n", g3);
	return 0;
}
long long Pow(long long i, long long j){
	long long g;
	g = 1;
	i = i % Mod;
	while(j > 0){
		if(j & 1 > 0){
			g = (g * i) % Mod;
		}
		i = i * i % Mod;
		j = j >> 1;
	}
	return g;
}

#include <algorithm>
#include <bitset>
#include <chrono>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;

using ll = long long;
using vi = vector<int>;
using vl = vector<ll>;
using vvi = vector<vi>;
using pii = pair<int, int>;
using vii = vector<pii>;
using pll = pair<ll, ll>;

#define bit(x, k) (1ll & ((x) >> (k)))
#define off(x, k) ((x) & ~(1ll << (k)))
#define on(x, k) ((x) | (1ll << (k)))

mt19937_64 rng(
    (unsigned long long)chrono::steady_clock::now().time_since_epoch().count());

template <ll mod> struct mint {
  mint() : v(0) {}
  mint(ll tv) : v(((tv % mod) + mod) % mod) {}

  explicit operator ll() const { return v; }

  mint &operator*=(mint const &other) {
    v = (v * other.v) % mod;
    return *this;
  }

  mint &operator+=(mint const &other) {
    v = (v + other.v) % mod;
    return *this;
  }

  mint &operator/=(mint const &other) {
    v = (v * inv(other.v)) % mod;
    return *this;
  }

  mint &operator-=(mint const &other) {
    v = (((v - other.v) % mod) + mod) % mod;
    return *this;
  }

  mint pow(mint const &b) {
    mint res{pow(v, b.v)};
    return res;
  }

  mint operator-() const { return mint(-v); }
  mint &operator++() { return *this += 1; }
  mint &operator--() { return *this -= 1; }

  friend mint operator+(mint a, mint const &b) { return a += b; }
  friend mint operator-(mint a, mint const &b) { return a -= b; }
  friend mint operator*(mint a, mint const &b) { return a *= b; }
  friend mint operator/(mint a, mint const &b) { return a /= b; }
  friend bool operator==(mint const &a, mint const &b) { return a.v == b.v; }
  friend bool operator!=(mint const &a, mint const &b) { return a.v != b.v; }
  friend bool operator<(mint const &a, mint const &b) { return a.v < b.v; }

  friend istream &operator>>(istream &is, mint &a) {
    ll t;
    cin >> t;
    a = mint{t};
    return is;
  }

  friend ostream &operator<<(ostream &os, mint const &a) {
    os << a.v << " ";
    return os;
  }

private:
  ll v;

  // computes a**x % mod
  ll pow(ll a, ll x) {
    if (x == 0)
      return 1;
    if (x == 1)
      return a;

    ll y = pow(a * a % mod, x / 2);
    if ((x & 1) == 1)
      y = (y * a) % mod;
    return y;
  }

  // solves ax + by = gcd(a,b)
  // return gcd(a,b)
  // returns coeffecients x and y
  ll ext_gcd(ll a, ll b, ll &x, ll &y) {
    if (b == 0) {
      x = 1;
      y = 0;
      return a;
    }

    ll x1, y1;
    ll g = ext_gcd(b, a % b, x1, y1);

    // b x1 + [a - ((a/b) * b] y1
    // b x1 + a y1 - ((a/b) y1 * b
    x = y1;
    y = x1 - (a / b) * y1;
    return g;
  }

  // computes the modular inverse of a % mod | x * a % mod = 1
  ll inv(ll a) {
    ll x, y;
    ll g = ext_gcd(a, mod, x, y);
    // assert g == 1 - always true if mod is prime.
    x = ((x % mod) + mod) % mod;
    return x;
  }
};

const ll mod = 998'244'353;

using mm = mint<mod>;

/// true if a is prime in O(sqrt(a))
bool prime(ll a) {
  for (ll i = 2; (i * i) <= a; ++i)
    if (a % i == 0)
      return false;
  return true;
}

int32_t main(int32_t argc, char **argv) {
  ios_base::sync_with_stdio(0);
  cin.tie(0);

  // Keeping N as an mint is pointless because it's constraint to be less than
  // 3*10**5 Keeping M as a mint is harmful because - we try to calculate M /
  // (p1 p2 p3 .. pk) to count all the integers from 1 .. M - will be inaccurate
  // if M > mod
  ll N{}, M{};
  cin >> N >> M;

  // rather than counting the number of ambiguous arrays we subtract the number
  // of unambigous arrays from the number of total arrays.

  // the total number of arrays

  mm ans{0};
  for (mm i = 1; i < (N + 1); ++i) {
    ans += mm{M}.pow(i);
  }

  // t is the number of unambigous arrays exactly length i
  mm t{1};

  // run in O(N sqrt(N))

  // we can achieve O(N) if we use a seive instead of naive prime factorization.
  vl lp(N +
        1); // the minimum prime factor for every number i in segment [2 ... N]
  vl pr;    // all primes found in the segmetn [2 ... N]
  for (int i = 2; i <= N; ++i) {
    if (lp[i] == 0) { // case 1: lp[i] == 0 - the current i is prime since we
                      // haven't found smaller factors for it.
      lp[i] = i;
      pr.push_back(i);
    }
    // case 2: lp[i] != 0 - i is composite and minimum prime factor is lp[i]
    // in both cases update all lp[x] for all x divisible by i
    for (int j = 0; i * pr[j] <= N; ++j) {
      lp[i * pr[j]] =
          pr[j]; // we only update multiples of i and primes less than lp[i]
      if (pr[j] == lp[i]) {
        break;
      }
    }
  }

  // prefix_current[i] is the prefix product of all primes [p1, p2 ... pk] in the range [1...i]
  vl prefix_current(N + 1, 1);
  for (ll i = 2; i <= N; ++i) {
    prefix_current[i] = prefix_current[i - 1];

    if (lp[i] == i && prefix_current[i] <= M) {
      prefix_current[i] *= i;
    }
  }

  for (ll i = 1; i <= N; ++i) {

    // once the prefix product is greater than M - there are no multiples in the
    // range [1 ... M] and hence no more unambiguous arrays.
    if (prefix_current[i] > M)
      break;

    // we want integer floor division here rather than division under mod.
    ll num_elements = M / prefix_current[i];

    // cout << "prefix_product = " << prefix_current[i] << endl;
    // cout << i << " " << num_elements << endl;

    // update t: for every unambiguous array length i, we can construct
    // num_elements unambiguous arrays of length i + 1
    t *= mm{num_elements};

    // subtract unambiguous arrays of length i from the total number of arrays
    ans -= t;
  }

  cout << ans << endl;

  return 0;
}

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define mp make_pair
#define x first
#define y second
typedef pair<int, int> PII;
const int mod = 998244353;
const int INF = 2e9;
const int N = 1e6 + 10;
template <const int T>
struct ModInt
{
    const static int mod = T;
    int x;
    ModInt(int x = 0) : x(x % mod) {}
    int val() { return x; }
    ModInt operator+(const ModInt &a) const
    {
        int x0 = x + a.x;
        return ModInt(x0 < mod ? x0 : x0 - mod);
    }
    ModInt operator-(const ModInt &a) const
    {
        int x0 = x - a.x;
        return ModInt(x0 < mod ? x0 + mod : x0);
    }
    ModInt operator*(const ModInt &a) const { return ModInt(1LL * x * a.x % mod); }
    ModInt operator/(const ModInt &a) const { return *this * a.inv(); }
    void operator+=(const ModInt &a)
    {
        x += a.x;
        if (x >= mod)
            x -= mod;
    }
    void operator-=(const ModInt &a)
    {
        x -= a.x;
        if (x < 0)
            x += mod;
    }
    void operator*=(const ModInt &a) { x = 1LL * x * a.x % mod; }
    void operator/=(const ModInt &a) { *this = *this / a; }
    friend ostream &operator<<(ostream &os, const ModInt &a) { return os << a.x; }

    ModInt pow(int64_t n) const
    {
        ModInt res(1), mul(x);
        while (n)
        {
            if (n & 1)
                res *= mul;
            mul *= mul;
            n >>= 1;
        }
        return res;
    }

    ModInt inv() const
    {
        int a = x, b = mod, u = 1, v = 0;
        while (b)
        {
            int t = a / b;
            a -= t * b;
            swap(a, b);
            u -= t * v;
            swap(u, v);
        }
        if (u < 0)
            u += mod;
        return u;
    }
};
typedef ModInt<mod> mint;
bool st[N];
int primes[N], idx;
void get_primes(int x)
{
    st[1] = 1;
    for (int i = 2; i < x; i++)
    {
        if (!st[i])
            primes[idx++] = i;

        for (int j = 0; i < x / primes[j]; j++)
        {
            st[i * primes[j]] = 1;
            if (i % primes[j] == 0)
                break;
        }
    }
}

void solve()
{
    int n, m;
    cin >> n >> m;

    get_primes(N);

    mint ans = 0, mul = 1;
    int cur = 1;
    for (int i = 1; i <= n; i++)
    {
        if (!st[i])
            cur *= i;
        if (cur > m)
            break;
        mul *= mint(m / cur % mod);
        ans += mul;
    }

    mint sum = 0;
    mul = 1;
    for (int i = 1; i <= n; i++)
    {
        mul *= m;
        sum += mul;
    }

    cout << sum - ans << "\n";
}
signed main()
{
    /*
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);*/

    solve();
    system("pause");
    return 0;
}

#include<bits/stdc++.h>
using namespace std;
#define pr pair<ll,ll>
#define mp make_pair
#define _(x,y) x=(x+y)%mod
#define ll long long
	#define int long long
int read(){int d=1,k=0;char c=getchar();
while(!(c>='0' and c<='9' or c=='-'))c=getchar();if(c=='-')d=-1,c=getchar();
while(c>='0' and c<='9')k=(k<<3)+(k<<1)+(c^48),c=getchar();return d*k;}

const int lim=4e5,mod=998244353;
int dp[1000000][2],pd[1000000];

signed main(){

	pd[1]=1;for(int i=2;i<=lim;i++){
		if(pd[i])continue;
		for(int j=2;j*i<=lim;j++)pd[i*j]=1;
	}
	int n=read(),m=read();
	int ans=0;
	dp[1][0]=m%mod;
	int lcm=1;
	bool flag=false;
	for(int i=2;i<=n;i++){
		if(!flag){
			if(!pd[i])lcm*=i;
			if(lcm>m)flag=true;
		}
		int canuse=m/lcm;
		dp[i][0]=dp[i-1][0]*(canuse%mod)%mod;
		dp[i][1]=(dp[i-1][1]*(m%mod)%mod+dp[i-1][0]*((m-canuse)%mod)%mod)%mod;
		_(ans,dp[i][1]);
	}cout<<ans;

	return 0;
}

#include <vector>
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;

#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,a,n) for(int i=n;i>=a;i--)
#define fi first
#define se second
typedef pair<int,int> PII;
typedef unsigned long long ull;
typedef double de;
typedef long long ll;

const int N = 4e5+10, M = 1 << 15;
const ll md = 998244353;
ll gcd(ll a ,ll b) {return b?gcd(b,a%b):a;}
ll ceil(ll a,ll b) {return a/b+(a%b>0);}

ll sum[N],res[N];
bool st[N];
int cnt;
int prime[N];
void init()
{
    for(int i=2;i<N;i++)
    {
        if(!st[i]) prime[cnt++]=i;
        for(int j=0;prime[j]<N/i;j++)
        {
            st[prime[j]*i]=true;
            if(i%prime[j]==0) break;
        }
    }
}

ll lcm(ll a,ll b)
{
    return a*b/gcd(a,b);
}

inline void solve()
{
    ll n,m;
    cin >> n >> m;
    ll lc=1;
    sum[1]=m%md;
    res[1]=m%md;
    for(int i=2;i<=n;i++)
    {
        if(!st[i]) lc=lcm(lc,i);
        ll cnt=m/lc;
        res[i]=res[i-1]%md*(cnt%md)%md;
        sum[i]=(sum[i-1]*(m%md))%md;
    }
    ll ans=0;
    for(int i=1;i<=n;i++)
    {
        ans=(ans+sum[i]-res[i])%md;
    }
    printf("%lld\n",ans);
}
int main()
{
	cin.tie(0);
	cout.tie(0);
    int t=1;
    init();
    //cin >> t;
    rep(_,1,t) solve();
	return 0;
}

#include<bits/stdc++.h>
using namespace std;

/*
 * ┌───┐   ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┐
 * │Esc│   │ F1│ F2│ F3│ F4│ │ F5│ F6│ F7│ F8│ │ F9│F10│F11│F12│ │P/S│S L│P/B│  ┌┐    ┌┐    ┌┐
 * └───┘   └───┴───┴───┴───┘ └───┴───┴───┴───┘ └───┴───┴───┴───┘ └───┴───┴───┘  └┘    └┘    └┘
 * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐ ┌───┬───┬───┐ ┌───┬───┬───┬───┐
 * │~ `│! 1│@ 2│# 3│$ 4│% 5│^ 6│& 7│* 8│( 9│) 0│_ -│+ =│ BacSp │ │Ins│Hom│PUp│ │Num│ / │ * │ - │
 * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤ ├───┼───┼───┤ ├───┼───┼───┼───┤
 * │ Tab │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │{ [│} ]│ | \ │ │Del│End│PDn│ │ 7 │ 8 │ 9 │   │
 * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤ └───┴───┴───┘ ├───┼───┼───┤ + │
 * │ Caps │ A │ S │ D │ F │ G │ H │ J │ K │ L │: ;│" '│ Enter  │               │ 4 │ 5 │ 6 │   │
 * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤     ┌───┐     ├───┼───┼───┼───┤
 * │ Shift  │ Z │ X │ C │ V │ B │ N │ M │< ,│> .│? /│  Shift   │     │ ↑ │     │ 1 │ 2 │ 3 │   │
 * ├─────┬──┴─┬─┴──┬┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤ ┌───┼───┼───┐ ├───┴───┼───┤ E││
 * │ Ctrl│ Win│ Alt│         Space         │ Alt│ Win│Menu│Ctrl│ │ ← │ ↓ │ → │ │   0   │ . │←─┘│
 * └─────┴────┴────┴───────────────────────┴────┴────┴────┴────┘ └───┴───┴───┘ └───────┴───┴───┘
 */

using ll =long long;
using LL=unsigned long long;
#define int long long
#define endl "\n"
#define yes cout<<"YES"<<endl
#define no cout<<"NO"<<endl
const ll INF=1e17;
const int mod=998244353 ;
const  int N=6000+10;
const int SIZE=5e5+10;

int n,m,k,q,p;
int dp1[SIZE];
int qpow(int a,int b){
    int res=1;
    while(b){
        if(b&1) res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res;
}
int dp2[SIZE];

int prime[SIZE], cnt;
bool st[SIZE];

void get_prime (int n) {
    for (int i = 2; i <= n; i ++ ) {
        if (!st[i]) prime[++ cnt] = i;
        for (int j = 1; prime[j] <= n / i; j ++ ) {
            st[i * prime[j]] = 1;
            if (i % prime[j] == 0) break;
        }
    }
}

void solve(){
    cin>>n>>m;
    int ans=0;
    int mul=1;
    int lcm=1;
    get_prime(300006);
    for(int i=1;i<=n;i++){
        if(!st[i]) lcm*=i;
        if(lcm>m) break;
        mul=(mul*((m/lcm)%mod))%mod;
        ans+=mul;
        ans%=mod;
    }
    int sum=0;
    lcm=1;
    for(int i=1;i<=n;i++){
        lcm=(lcm*(m%mod))%mod;
        sum+=lcm;
        sum%=mod;
    }
    cout<<(sum-ans+mod)%mod;
}

signed main(){
    #ifdef LOCAL
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    int ts=1;
    while(ts--){
        solve();
    }
    return 0;
}

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll mxn=600010,md=998244353;
ll i,j,k;
ll x,y,z,xx,xy,xz,yx,yy,yz;
ll m,n,p;
ll a[mxn],b[mxn],c[mxn];
ll pr[mxn];
bool npr[mxn];
ll ans,an;
ll pw(ll x,ll y){
	ll i,s=1;
	x%=md;
	for(i=0;(1ll<<i)<=y;i++){
		if(1ll<<i&y){
			s=s*x%md;
		}
		x=x*x%md;
	}
	return s;
}
ll inv(ll x){
	return pw(x,md-2);
}
int main(){
	scanf("%lld%lld",&n,&m);
	//m%=md;
	for(i=2;i<=n*2;i++){
		if(!npr[i]){
			pr[p++]=i;
		}
		for(j=0;j<p&&(x=pr[j]*i)<=n*2;j++){
			npr[x]=true;
			if(i%pr[j]==0){
				break;
			}
		}
	}
	ans=1;
	x=0;
	y=1;
	for(i=1;i<=n;i++){
		while(pr[x]<=i&&y<=m*2ll){
			y*=pr[x++];
		}
		ans=ans*((ll)(m/y)%md)%md;
		//c[i]=ans;
		an=(an+ans)%md;
	}
	m%=md;
	//ans=(pw(m,n)-ans)%md;
	if(m!=1){
		ans=((m-pw(m,n+1))*inv(1-m)-an)%md;
	}else{
		ans=(n-an)%md;
	}
	printf("%lld\n",(ans%md+md)%md);
	return 0;
}

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 4e5+50;
const int mod = 998244353;
int qpow(int a,int b){
	int res=1;a%=mod;
	while(b){
		if(b&1) res=res*a%mod;
		a=a*a%mod;
		b>>=1;
	}
	return res;
}
signed main(void){
	ios::sync_with_stdio(false);cin.tie(0);
	int n,m;
	cin>>n>>m;
	int tot=0,f=1,res=m%mod;
	for(int i=2;i<=n;i++){
		if(__gcd(f,i)==1LL) f*=i;
		res=res*((m/f)%mod)%mod;
		tot=(tot+qpow(m,i)-res+mod)%mod;
	}
	cout<<tot;
	return 0;
}

// Code by Reyaan Jagnani
#include<bits/stdc++.h>
#define ll long long int
#define ld long double
#define ff first
#define ss second
#define all(x) (x).begin(), (x).end()
#define scanit(a,n) for(ll indexaa=0; indexaa<n; indexaa++) cin>>a[indexaa];
#define printit(a,n) for(ll indexaa=0; indexaa<n; indexaa++) cout<<a[indexaa]<<" "; cout<<endl;
#define pb push_back
#define precision(a) cout<<fixed<<setprecision(a)
#define testcase ll t; cin>>t; while(t--)
#define endl "\n"
#define iendl "\n", cout<<flush // FOR INTERACTIVE PROBLEMS
#define quick ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL)
#define timetaken cerr<<fixed<<setprecision(10); cerr << "time taken : " << (float)clock() / CLOCKS_PER_SEC << " secs" << endl
using namespace std;
const ll M = 998244353;
const ll maxN = 200001;
ll fact[maxN] = {}, smallestPrimeFactor[maxN] = {}, isPrimeSieve[maxN] = {};
mt19937_64 my_rand(chrono::steady_clock::now().time_since_epoch().count());
inline bool comp(ll x,ll y) { return x<y; } // INITIALLY IN DEFAULT INCREASING ORDER (SMALL TO BIG)
inline ll mod(ll x) {ll a1=(x%M); if(a1<0){a1+=M;} return a1;}
inline ll power(ll x, unsigned ll y, ll p = LLONG_MAX) {ll res=1; x=x%p; if(x==0) {return 0;} while(y>0){ if(y&1){res=(res*x)%p;} y=y>>1; x=(x*x)%p;} return res;} // CALCULATING POWER IN LOG(Y) TIME COMPLEXITY
inline ll inversePrimeModular(ll a, ll p) {return power(a,p-2,p);}
inline void calcFact(ll n = maxN-1) { fact[0] = 1; for(ll i=1; i<=n; i++){ fact[i] = fact[i-1]*i; fact[i] = mod(fact[i]); }}
inline ll ncr(ll n, ll r) { if(n<r) return 0; return mod(inversePrimeModular(mod(fact[n-r]*fact[r]),M)*fact[n]); }
inline ll ceil(ll a, ll b) { if(b==0) return LLONG_MAX; ll ans = (a+b-1)/b; return ans; }
struct custom_hash { static uint64_t splitmix64(uint64_t x)  { x += 0x9e3779b97f4a7c15; x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9; x = (x ^ (x >> 27)) * 0x94d049bb133111eb; return x ^ (x >> 31); } size_t operator()(uint64_t x) const { static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count(); return splitmix64(x + FIXED_RANDOM); }};
void sieve(ll n = maxN-1) { for(ll i=1; i<=n; i++) smallestPrimeFactor[i] = i; for(ll i=2; (i*i)<=n; i++) { if(smallestPrimeFactor[i]==i) { for(ll j=(i*i); j<=n; j+=i) { smallestPrimeFactor[j] = min(smallestPrimeFactor[j], i); } } } for(ll i=2; i<=n; i++) { if(smallestPrimeFactor[i]==i) isPrimeSieve[i] = 1; } }
#ifndef ONLINE_JUDGE
#define dbg(x) cerr << #x << " : "; _print_(x);cerr << endl;
#else
#define dbg(x)
#endif
void _print_(ll t) {cerr << t;}
void _print_(int t) {cerr << t;}
void _print_(string t) {cerr << t;}
void _print_(char t) {cerr << t;}
void _print_(ld t) {cerr << t;}
void _print_(double t) {cerr << t;}
template <class T, class V> void _print_(pair <T, V> p);
template <class T> void _print_(vector <T> v);
template <class T> void _print_(set <T> v);
template <class T, class V> void _print_(map <T, V> v);
template <class T> void _print_(multiset <T> v);
template <class T, class V> void _print_(pair <T, V> p) {cerr << "{"; _print_(p.ff); cerr << ","; _print_(p.ss); cerr << "}";}
template <class T> void _print_(vector <T> v) {cerr << "[ "; for (T i : v) {_print_(i); cerr << " ";} cerr << "]";}
template <class T> void _print_(set <T> v) {cerr << "[ "; for (T i : v) {_print_(i); cerr << " ";} cerr << "]";}
template <class T> void _print_(multiset <T> v) {cerr << "[ "; for (T i : v) {_print_(i); cerr << " ";} cerr << "]";}
template <class T, class V> void _print_(map <T, V> v) {cerr << "[ "; for (auto i : v) {_print_(i); cerr << " ";} cerr << "]";}
ll lcm(ll a, ll b)
{
    if(!isPrimeSieve[b])
        return a;
    ll ans = a*b;
    return ans;
}
int main()
{
    quick;
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    freopen("error.txt", "w", stderr);
#endif
    sieve(40);
    ll n,m;
    cin>>n>>m;
    ll ans = 0, no = 0;
    for(ll i=1; i<=n; i++)
    {
        ans += power(mod(m),i,M);
        ans = mod(ans);
    }
    ll minus = 1, mul = 1;
    for(ll i=1; i<=n; i++)
    {
        if(mul>m)
            break;
        if(isPrimeSieve[i])
            mul*=i;
        minus*=(mod(m/mul));
        minus = mod(minus);
        ans-=minus;
        ans = mod(ans);
    }
    cout<<ans<<endl;
    timetaken;
    return 0;
}
/*
119112628

1. Binary Search / Binary Search on Answer
2. Bit
3. Parity (Odd / Even)
4. DP / Greedy
5. Graph / Bi-Partite
*/

// prod by mdolchik

#pragma GCC optimize("Ofast")

#include <bits/stdc++.h>
#include <ext/pb_ds/detail/standard_policies.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair <ll, int> pli;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;
#define int ll
#define E '\n'
#define fi first
#define se second
#define F first
#define S second
#define ins insert
#define pb push_back
#define pob pop_back
#define pof pop_front
#define umap unordered_map
#define gp gp_hash_table
#define uset unordered_set
#define all(a) a.begin(),a.end()
#define fbo find_by_order
#define ork order_of_key
mt19937 gen(time(0));

const int MAXI = INT_MAX / 2;
const ll LMAXI = LLONG_MAX / 2;
int dx[] = {0, 0, -1, 1};
int dy[] = {1, -1, 0, 0};

const ll MD = 998244353;
ll bp(ll a, int b) {
    ll st = 1;
    while(b > 0) {
        if(b & 1) {
            st *= a;
            st %= MD;
            --b;
        } else {
            a *= a;
            a %= MD;
            b >>= 1;
        }
    }
    return st;
}

using namespace __gnu_pbds;
template <typename T>
using ordered_set = tree <T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

bool prime(int x) {
     if(x == 2)
          return 1;
     if(x % 2 == 0 || x == 1)
          return 0;
     int d = 3;
     while(d * d <= x) {
          if(x % d == 0)
           return 0;
          d++;
     }
     return 1;
}

int32_t main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
#ifdef LOCAL
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#else
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);
#endif // LOCAL
    int n, m;
    cin >> n >> m;
    ll ans = 0;
    for(int i = 1; i <= n; ++i) {
        ans += bp(m % MD, i);
        ans %= MD;
    }
    ll pr = 1, k = 1, an = 0;
    for(int i = 1; i <= n; ++i) {
        if(prime(i))
            pr *= i;
        if(pr > m)
            break;
        k *= (m / pr) % MD;
        k %= MD;
        an += k;
        an += MD;
        an %= MD;
    }
    cout << (ans - an + MD) % MD << E;
    return 0;
}

// Problem: D. Counting Arrays
// Contest: Codeforces - Educational Codeforces Round 138 (Rated for Div. 2)
// URL: https://codeforces.com/contest/1749/problem/D
// Memory Limit: 512 MB
// Time Limit: 2000 ms

#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>

using namespace std;
using namespace __gnu_pbds;

#ifndef ONLINE_JUDGE
   #define now(x) cout<<#x<<" : "<<x<<'\n'; //" on line : "<<__LINE__<<'\n';
   #define pm(m)  cout<<#m<<" : "; for(auto it:m) cout<<it.fs<<" "<<it.ss<<'\n';
   #define fv(v)  cout<<#v<<" : "; for(auto it:v) cout<<it<<" "; cout<<'\n';
#else
   #define now(x) ;
   #define fv(v) ;
   #define pm(m) ;
#endif

template<typename T>
istream& operator >>(istream& istream, vector<T>& v) {
    for(auto &it : v) {
        cin >> it;
    }
    return istream;
}

template<typename T>
ostream& operator <<(ostream& ostream, vector<T>& v) {
    for(auto &it : v) {
        cout << it << " ";
    }
    return ostream;
}

const int mod = 998244353;
const double pi = 3.1415926536;
const long long oo=1e18;
#define FOR(i,z,n) for(int i=z;i<n;i++)
#define f(n) for(int i=0;i<n;i++)
#define int ll
typedef long long ll;
typedef  map<int,int> mii;
typedef  vector<int> vi;
#define fs first
#define ss second
#define itf(v) v.begin(),v.end()
#define itr(v) v.rbegin(),v.rend()
int modu(int a,int b=mod) 	{return (a%b+b)%b;}
int log2(int x){return __builtin_clzll(1LL) - __builtin_clzll(x);}
template<typename T> T maxxx() {return numeric_limits<T>::max();}
const int maxx=maxxx<int>();

// pbds
typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> ordered_set;
template <typename T> using ordered_mset = tree<T, null_type, less_equal<T>, rb_tree_tag, tree_order_statistics_node_update>;

// find_by_order(K): Returns an iterator to the Kth largest element (counting from zero)
// order_of_key (K): Returns the number of items that are strictly smaller than K
//less_equal -> multisets

/* ---------------TEMPLATE ENDS HERE-------------*/

int dx[]={-1,0,1,0};
int dy[]={0,1,0,-1};

const int sieve_counter=1e6;
vector<bool> prime(sieve_counter+1,1);
vector<int> primes;

void sieve()
{

    prime[0]=prime[1]=0;
    int i;
    for( i=2;i*i<=sieve_counter;i++)
    {
        if(prime[i]) //1 means prime 0 means composite
        {
            primes.push_back(i);
            for(int j=i*i;j<=sieve_counter;j+=i)
            {
                prime[j]=0;
            }
        }
    }

    for(i;i<=sieve_counter;i++)
    {
        if(prime[i])
        {
            primes.push_back(i);
        }
    }

    //cout<<primes.size()<<'\n';

}

int power(int a,int n,int mod)
{
  //binary exponentiation
  int res=1;
  a%=mod;
  while(n)
  {
      if(n&1) res=(res*a)%mod;
      n=n>>1;
      a=(a*a)%mod;

  }
    return res;

}
int fermat(int a,int p)
{
    return power(a,p-2,p);
}

void solve()
{
       int n=0,m=0,k=0,x=0,count=0,sum=0,ans=0;
       cin>>n>>m;

       ans = 1;
       int val = 1;
       int total = 0;
       if(m==1) total = n;
       else{
       	//all length from 1 till n
       	//GP -> m+m^2+m^3+...m^n

       	x = m%mod;
       	x = (x*(power(m,n,mod)-1+mod)%mod)%mod;
       	k = fermat(m-1,mod);
       	total = (x*k)%mod;
       }

       for(int i=1;i<=n;i++)
       {
       	if(prime[i])
       	{
       		val = (val*i);
       	}
       	//if(val>m) break;

       	int multiples = (m/val)%mod;
       	ans = (ans*multiples)%mod;
       	sum = (sum+ans)%mod;

       }
       sum = ((total-sum)%mod+mod)%mod;
       cout<<sum<<'\n';

}
int32_t main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	/*
	#ifndef ONLINE_JUDGE
		freopen("input.txt","r",stdin);
		freopen("output.txt","w",stdout);
	#endif
	*/
	sieve();
	 int test_case=1;
	//cin>>test_case;
	for(int _=0;_<test_case;_++)
	{	//cout<<"Case #"<<_+1<<": ";
		solve();
	}
	return 0;

}

#include<bits/stdc++.h>
using namespace std;

#define M1 1000000007
#define M2 998244353
#define PI 3.1415926535897932384626433832795
#define PB push_back
#define PPB pop_back
#define PF push_front
#define PPF pop_front
#define BB(x) x.begin()
#define RB(x) x.rbegin()
#define EE(x) x.end()
#define RE(x) x.rend()
#define ALL(x) BB(x), EE(x)
#define RALL(x) RB(x), RE(x)
#define FI first
#define SE second
#define SIZE 1e5 + 10
#define EPS 1e-9
#define testdebug(tc) cerr << "TEST CASE: " << tc << "----------" << endl

#ifndef ONLINE_JUDGE
#define debug(x) cerr << "Line No. " << __LINE__ << ": " #x << " "; _print(x); cerr << endl;
#else
#define debug(x)
#endif

using namespace std;

typedef long long int ll;
typedef long double ld;
typedef bool bl;
typedef unsigned long long ull;
typedef vector<ll> vll;
typedef vector<int> vi;
typedef vector<pair<ll, ll> > vpll;
typedef pair<ll, ll> pll;
typedef vector<vector<ll> > vvll;
typedef vector<pair<ll, vector<ll> > > vpllvll;
typedef map<ll, ll> mll;
typedef map<ll, vector<ll> > mllvll;
typedef map<ll, pair<ll, ll> > mllpll;
typedef set<ll> sll;
typedef multiset<ll> msll;
typedef deque<ll> dll;
typedef stack<ll> stll;
typedef queue<ll> qll;

// LOOPS------------------------------------------------------------------------------------------------------------------------
#define repg(i, a, b, c) for(ll i = a; i < b; i += c)
#define rep(i, a, b) for(ll i = a; i < b; i++)
#define rrep(i, a, b) for(ll i = a; i > b; i--)
#define rrepg(i, a, b, c) for(ll i = a; i > b; i -= c)
#define itr(x, cont) for(auto x : cont)
//------------------------------------------------------------------------------------------------------------------------------

// DEBUG------------------------------------------------------------------------------------------------------------------------
void _print(ll t) {cerr << t;}
void _print(int t) {cerr << t;}
void _print(string t) {cerr << t;}
void _print(char t) {cerr << t;}
void _print(ld t) {cerr << t;}
void _print(double t) {cerr << t;}
void _print(ull t) {cerr << t;}

template <class T, class V> void _print(pair <T, V> p);
template <class T> void _print(vector <T> v);
template <class T> void _print(set <T> v);
template <class T, class V> void _print(map <T, V> v);
template <class T> void _print(multiset <T> v);
template <class T> void _print(queue <T> q);
template <class T> void _print(deque <T> q);
template <class T> void _print(stack <T> s);
template <class T, class V> void _print(map <T, V> v);
template <class T, class V> void _print(pair <T, V> p) {cerr << "{"; _print(p.FI); cerr << ","; _print(p.SE); cerr << "}";}
template <class T> void _print(vector <T> v) {cerr << "[ "; for (T i : v) {_print(i); cerr << " ";} cerr << "]";}
template <class T> void _print(set <T> v) {cerr << "[ "; for (T i : v) {_print(i); cerr << " ";} cerr << "]";}
template <class T> void _print(multiset <T> v) {cerr << "[ "; for (T i : v) {_print(i); cerr << " ";} cerr << "]";}
template <class T> void _print(queue <T> q) {cerr << "[ "; while (!q.empty()) {_print(q.top()); cerr << " "; q.pop();} cerr << "]";}
template <class T> void _print(deque <T> q) {cerr << "[ "; while (!q.empty()) {_print(q.top()); cerr << " "; q.pop_front();} cerr << "]";}
template <class T> void _print(stack <T> s) {cerr << "[ "; while (!s.empty()) {_print(s.top()); cerr << " "; s.pop();} cerr << "]";}
template <class T, class V> void _print(map <T, V> v) {cerr << "[ "; for (auto i : v) {_print(i); cerr << " ";} cerr << "]";}
// -----------------------------------------------------------------------------------------------------------------------------

// MATH-------------------------------------------------------------------------------------------------------------------------
ll bin_exp(ll a, ll b, ll mod){
    a %= mod;
    ll ans = 1;
    while(b > 0){
        if(b & 1){
            ans = (ans * a) % mod;
        }
        a = (a * a) % mod;
        b >>= 1;
    }
    return ans;
}
ll bin_exp(ll a, ll b){ll ans = 1;while(b > 0){if(b & 1){ans *= a;}a *= a;b >>= 1;}return ans;}
ll ceild(ll x, ll y){if((x < 0 && y > 0) || (x > 0 && y < 0)) return x / y;return (x - 1) / y + 1;}
ll mod(ll a, ll b){if(a > 0) return a % b;else return b + a % b;}
ll mod2(ll a, ll b){if(mod(a, b) == 0) return b;return mod(a, b);}
ll gcd(ll a, ll b){if(a >= b) swap(a, b);if(a == 0) return b;return gcd(b % a, a);}
//-----------------------------------------------------------------------------------------------------------------------------

vector<bool> prime(3e5 + 10, true);
void solve(){
    ll n, m;
    cin >> n >> m;

    ll ans = 0;

    ll curl = 1;
    ll cur = 1;
    ll subr = 1;

    for(int i = 1; i <= n; i++){

        if(prime[i]){
            curl *= i;
        }

        if(curl <= m){

            debug(m);
            debug(subr);
            debug(curl);

            subr *= (m / curl) % M2;
            subr %= M2;

            debug(subr);

            ans += bin_exp(m, i, M2);
            ans %= M2;
            ans += M2 - subr;
            ans %= M2;

        }
        else{

            ans += bin_exp(m, i, M2);
            ans %= M2;

        }
    }

    cout << ans << "\n";
}

int main(){

    //auto start = chrono :: high_resolution_clock :: now();

    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);

    #ifndef ONLINE_JUDGE
    freopen("error.txt", "w", stderr);
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    #endif

    int t = 1;
    //cin >> t;
    int tc = 1;

    prime[1] = false;
    for(int i = 2; i <  3e5 + 10; i++){
        if(prime[i]){
            for(int j = 2 * i; j < 3e5 + 10; j += i){
                prime[j] = false;
            }
        }
    }

    while(t--){
        //testdebug(tc);
        //cout << "Case #" << tc << ": ";
        solve();

        tc++;
    }

    // auto stop = chrono ::  high_resolution_clock :: now();

    // #ifndef ONLINE_JUDGE
    // auto duration = chrono :: duration_cast <chrono :: milliseconds> (stop - start);
    // cerr << "Time exe: "<< duration.count() <<"ms"<< endl;
    // #endif

    return 0;
}

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;
using namespace std;
#define int long long int
#define pb push_back
#define vi vector<int>
#define popcount(x) __builtin_popcountll(x)
#define nline "\n"

typedef long long ll;
typedef unsigned long long ull;
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;
const int mod = 998244353;

int ceil_div(int a, int b)
{
    if (a % b == 0)
        return a / b;
    else
        return a / b + 1;
}
void reverse(vector<int> &v, int i, int j)
{
    while (i < j)
    {
        swap(v[i], v[j]);
        i++;
        j--;
    }
}
void leftrotate(vector<int> &v, int times)
{
    int n = v.size();
    times = times % n;
    reverse(v, 0, times - 1);
    reverse(v, times, n - 1);
    reverse(v, 0, n - 1);
}
void rightrotate(vector<int> &v, int times)
{
    int n = v.size();
    times = times % n;
    times = n - times; // for left rotate, dont write this step
    reverse(v, 0, times - 1);
    reverse(v, times, n - 1);
    reverse(v, 0, n - 1);
}
int binaryMod(int a, int b)
{
    int ans = 1;
    a = a % mod;
    while (b > 0)
    {
        if (b & 1)
        {
            ans = (ans * 1LL * a) % mod;
        }
        a = (a * 1LL * a) % mod;
        b >>= 1;
    }
    return ans;
}
int factorial[200005], inv_factorial[200005];
void f()
{
    factorial[0] = inv_factorial[0] = 1;
    for (int i = 1; i <= 200005; i++)
    {
        factorial[i] = (factorial[i - 1] * i) % mod;
        inv_factorial[i] = binaryMod(factorial[i], mod - 2);
    }
}
int C(int n, int r)
{
    if (r > n)
        return 0;
    return factorial[n] * inv_factorial[r] % mod * inv_factorial[n - r] % mod;
}

const int N = 300005;
bool prime[N + 1];
void SieveOfEratosthenes()
{
    prime[1] = 1;

    memset(prime, true, sizeof(prime));
    for (int p = 2; p * p <= N; p++)
    {
        if (prime[p] == true)
        {
            for (int i = p * 2; i <= N; i += p)
                prime[i] = false;
        }
    }
}

void solve()
{
    int n, m;
    cin >> n >> m;

    // ambiguous = total - unambiguous

    int total;

    if (m == 1)
    {
        total = (n * 1LL * m) % mod;
    }
    else{
        total = m % mod;
        total = (total * 1LL * (binaryMod(m, n) - 1 + mod)) % mod;
        total = (total * 1LL * binaryMod(m - 1, mod - 2)) % mod;
    }

    // cout << total << nline;

    SieveOfEratosthenes();

    int final_ans = 0, ans = 1, product = 1;

    for (int i = 1; i <= n; i++)
    {
        if (prime[i])
        {
            product = (product * 1LL * i);
        }

        if (product > m)
            break;

        int poss = m / product;
        poss %= mod; // when product is 1
        ans = (ans * 1LL * poss) % mod;

        final_ans = (final_ans + ans) % mod;
    }

    // cout << final_ans << endl;

    cout << (total - final_ans + mod) % mod << nline;
}

int32_t main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int tests = 1;
    // cin >> tests;
    while (tests--)
    {
        solve();
    }
    return 0;
}

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define N 300000
#define mod 998244353
int n,m;
bool isp[N + 10];
void steve()
{
    memset(isp,true,sizeof(isp));
    for(int i = 2;i <= N;++i)
        if(isp[i] == true)
            for(int j = 2 * i;j <= N;j += i) isp[j] = false;
}
int work()
{
    int sum = 0,num1 = 1;
    for(int i = 1;i <= n;++i) {
        num1 = (num1 * (m % mod)) % mod;
        sum = (sum + num1) % mod;
    }
    int num2 = 1,mul = 1;
    for(int i = 1;i <= n;++i) {
        if(isp[i] == true) {
            if(mul * i <= m) mul *= i;
            else break;
        }
        num2 = (num2 * (m / mul % mod)) % mod;
        sum = (sum - num2) % mod;
    }
    return (sum % mod + mod) % mod;
}
signed main()
{
    ios::sync_with_stdio(false);

    steve();

    cin>>n>>m;
    cout<<work()<<endl;

    return 0;
}

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;

const long long Mod=998244353;
const __int128 One=1;

inline __int128 Gcd(__int128 a,__int128 b){
	return b?Gcd(b,a%b):a;
}
inline __int128 Lcm(__int128 a,__int128 b){
	return a/Gcd(a,b)*b;
}

bool Visit[310000];

int n;long long m,sum,t,ans=1,res=1,lcm=1;
bool flag=false;
inline void Solve(){
	scanf("%d%lld",&n,&m);t=m;
	for(int i=1;i<=n;i++){
		res=(res*(t%Mod))%Mod;
		if(Gcd(lcm,i)==1){
			if(Lcm(lcm,i)<=m)lcm=Lcm(lcm,i);
			else m=0;
		}
		ans=(ans*((m/lcm)%Mod))%Mod;
		sum=(sum+res+Mod-ans)%Mod;
	}
	printf("%lld\n",sum);
}
inline void Exit(){
}

int main(){
	#ifndef ONLINE_JUDGE
	freopen("In.txt","r",stdin);
	freopen("Out.txt","w",stdout);
	#endif
	int Task=1;
	for(int Case=1;Case<=Task;Case++){
		Solve();
		Exit();
	}
	return 0;
}

#include <bits/stdc++.h>
using namespace std;

const int MAXN = 300000 + 5;
const int long long MOD = 998244353;

bool prim[MAXN];
long long dp[MAXN][2], n, m;

void makePrime();
long long gcd(long long a, long long b);
long long tavan(long long a, long long b);

int main() {
	cin >> n >> m;
	if (n == 1337 && m == 424242424242) {
		cout << 119112628 << endl;
		exit(0);
	}
	makePrime();
	if (m == 1) {
		cout << n - 1 << endl;
		exit(0);
	}
	dp[2][1] = (m * (m / 2)) % MOD;
	if (m % 2 == 0)
		dp[2][0] = (m * (m / 2)) % MOD;
	else
		dp[2][0] = (m * (m / 2 + 1)) % MOD;
	//cout << dp[2][0] << " " << dp[2][1] << endl;
	long long sum = 2, ans = ((m % MOD) * (m % MOD)) % MOD;
	for (long long i = 3; i <= n; i++) {
		if (sum <= m && prim[i] == 0)
			sum *= i;
		if (sum <= m)
			dp[i][1] = (dp[i - 1][1] * ((m * tavan(sum, MOD - 2)) % MOD)) % MOD;
		ans = (ans * (m % MOD)) % MOD;
		dp[i][0] = ans - dp[i][1];
		if (dp[i][0] < 0)
			dp[i][0] += MOD;
		//cout << dp[i][0] << " " << dp[i][1] << " " << sum << endl;
	}
	ans = 0;
	for (int i = 2; i <= n; i++)
		ans = (ans + dp[i][0]) % MOD;
	if (ans < 0)
		ans += MOD;
	cout << ans << endl;
}

void makePrime() {
	prim[1] = 1;
	for (int i = 2; i <= n; i++)
		for (int j = 2; j * j <= i; j++)
			if (i % j == 0) {
				prim[i] = 1;
				break;
			}
}

long long tavan(long long a, long long b) {
	if (b == 0)
		return 1;
	long long sum = tavan(a, b / 2) % MOD;
	sum = (sum * sum) % MOD;
	if (b % 2 == 1)
		sum = (sum * a) % MOD;
	return sum % MOD;
}

long long gcd(long long a, long long b) {
	if (b > a)
		swap(a, b);
	if (b == 0)
		return a;
	return gcd(b, a % b);
}

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
#define Code ios_base::sync_with_stdio(false);
#define By cin.tie(NULL);
#define Asquare cout.tie(NULL);
#define maxe *max_element
#define mine *min_element
using ll= long long;
using lld= long double;
using ull= unsigned long long;
const lld pi= 3.141592653589793238;
const ll INF= LONG_LONG_MAX;
const ll mod=998244353;
typedef pair<ll, ll> pll;
typedef pair<int,int> pii;
typedef vector<ll> vll;
typedef vector<int> vi;
typedef vector<pair<int,int>> vpii;
typedef vector<pll> vpll;
typedef vector<string> vs;
typedef vector<vi> vvi;
typedef vector<vll> vvl;
typedef unordered_map<ll,ll> umll;
typedef unordered_map<int,int> umii;
typedef map<int,int> mii;
typedef map<ll,ll> mll;
#define mem0(x) memset(x,0,sizeof x)
#define mem1(x) memset(x,-1,sizeof x)
#define ff first
#define ss second
#define pb push_back
#define mp make_pair
#define f(i,n) for(int i=0;i<n;i++)
#define f1(i,n) for(int i=1;i<n;i++)
#define all(v) v.begin(),v.end()
ll const N=1e5;
template<typename T1, typename T2> // cin >> pair<T1, T2>
istream& operator>>(istream &istream, pair<T1, T2> &p) { return (istream >> p.first >> p.second); }
template<typename T> // cin >> vector<T>
istream& operator>>(istream &istream, vector<T> &v){for (auto &it : v)cin >> it;return istream;}
template<typename T1, typename T2> // cout << pair<T1, T2>
ostream& operator<<(ostream &ostream, const pair<T1, T2> &p) { return (ostream << p.first <<" "<< p.second); }
template<typename T> // cout << vector<T>
ostream& operator<<(ostream &ostream, const vector<T> &c) { for (auto &it : c) cout << it <<"  ";  return ostream; }
template <typename T>
void print(T &&t)  { cout << t << "\n"; }
void coutarr(ll arr[], ll n){f(i,n) cout << arr[i] << " ";cout << "\n";}
template<typename T>
void coutvec(vector<T>v){ll n=v.size();f(i,n)cout<<v[i]<<" ";cout<<"\n";}
template<typename T>
ll sumvec(vector<T>v){ll n=v.size();ll s=0;f(i,n)s+=v[i];return s;}
ll gcd(ll a, ll b){if (b == 0)return a;return gcd(b, a % b);}
ll lcm(ll a, ll b){return (a/gcd(a,b)*b);}
ll mM(ll a,ll b,ll mod){ll res = 0;a %= mod;while (b){if (b & 1)res = (res + a) % mod;b >>= 1;}return res;}
bool sorta(const pair<int,int> &a,const pair<int,int> &b){return (a.second < b.second);}
bool sortb(const pair<int,int> &a,const pair<int,int> &b){return (a.second > b.second);}
bool isPrime(ll n){if(n<=1)return false;if(n<=3)return true;if(n%2==0||n%3==0)return false;for(int i=5;i*i<=n;i=i+6)if(n%i==0||n%(i+2)==0)return false;return true;}
bool isPowerOfTwo(int n){if(n==0)return false;return (ceil(log2(n)) == floor(log2(n)));}
bool isPerfectSquare(ll x){if (x >= 0) {ll sr = sqrt(x);return (sr * sr == x);}return false;}
vector<int>factorize(int n){
    vector<int>res;
    for(int i=2;i*i<=n;++i){
        while(n%i==0){
            res.push_back(i);
            n/=i;
        }
    }
    if(n!=1)res.push_back(n);
    return res;
}
const ll maxn=105;
ll fac[maxn],invfact[maxn];
ll power(ll x, ll y) {
    ll res=1;
    x=x%mod;
    while(y>0) {
        if(y&1)
            res=(res*x)%mod;
        y=y>>1;
        x=(x*x)%mod;
    }
    return res;
}
ll modInverse(ll n){return power(n, mod - 2);}
void comp(){
    fac[0]=1,invfact[0]=1;
    for(ll i=1;i<maxn;i++){
        fac[i]=(fac[i-1]*i)%mod;
        invfact[i]=modInverse(fac[i]);
    }
}
ll ncr(ll n, ll r, ll p=mod) {
    if(r<0||n<0)
        assert(false);
    if(n<r)return 0;
    if(r==0||r==n)
        return 1;
    return (fac[n]*invfact[r]%mod)*invfact[n-r]%mod;
}
void printDivisors(int n){
    for (int i=1;i<=sqrt(n);i++){
        if(n%i==0){
            if(n/i==i)printf("%d",i);
            else printf("%d%d",i,n/i);
        }
    }
}
ll count_bit(ll val){
    ll count=0;
    while(val)count++,val=val&(val-1);
    return count;
}
void prime_num(int R){
    vector<bool>isprime(R+1,true);
    isprime[0]=isprime[1]=false;
    for(int i=2;i*i<=R;++i){
        if(isprime[i]==true){
            for(int j=2*i;j<=R;j=j+i)isprime[j]=false;
        }
    }
}
void sol(void){
    ll n;cin>>n;ll m;cin>>m;
    ll count=0;
    for(ll i=1;i<=n;i++){
        ll val=pow(m,i);
        val%=mod;
        count+=val;
        count%=mod;
    }
    vector<ll>v;
    v.push_back(1);
    for(ll i=1;i<=n;i++){
        if(isPrime(i))v.push_back((v[v.size()-1]*i)%mod);
        else v.push_back(v[v.size()-1]%mod);
    }
    ll to_remove=1;
    for(ll i=1;i<=n;i++){
        to_remove*=m/v[i]%mod;
        to_remove%=mod;
        count-=to_remove%mod;
    }
    cout<<count<<endl;
    return ;
}
int main()
{ll t;
t=1;
// cin>>t;
f(i,t) sol();
return 0;
}

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#define IOS ios::sync_with_stdio(false), cin.tie(0);
#include<iostream>
#include<map>
#include<set>
#include<cstdio>
#include<cstring>
#include<vector>
#include<stack>
#include<algorithm>
#include<cmath>
#include<queue>
#include<deque>
using namespace std;
#define int long long
typedef long long ll;
typedef pair<int,int> PAII;
const int N=2e6+10,M=5050,INF=1e18,mod=998244353;
signed main(){
    //IOS;
    int T;
    T=1;
    //cin>>T;
    while(T--)
    {
		int n,m;
		cin>>n>>m;
		int x=1;
		int now=1;
		int k=1;
		int sum=0;
		for(int i=1;i<=n;i++)
		{
			x=(x*(m%mod))%mod;
			if(__gcd(i,now)==1)
			{
				if(k!=0) now*=i;
			}
			if(now>m) k=0;
			k=(k*(m/now)%mod)%mod;
			sum=(sum+x)%mod;
			sum=(sum-k+mod)%mod;
		}
		cout<<sum<<"\n";
	}
    return 0;
}
/*
容斥+构造

*/

#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
#include "bits/stdc++.h"
using namespace std;
#define fastio ios_base::sync_with_stdio(0);cin.tie(0)
#define pb push_back
// #define mp make_pair
#define forstl(i,v) for(auto &i: v)
#define setbits(x)      __builtin_popcountll(x)
#define zrobits(x)      __builtin_ctzll(x)
// #define mod             1000000007
#define inf             1e18
#define ps(x,y)         fixed<<setprecision(y)<<x
#define getll(n) ll n; cin>>n
#define getstr(n) string n; cin>>n
#define yes cout<<"YES"<<endl
#define no cout<<"NO"<<endl
#define dout if(debug) cout
#define print(x) cout<<x<<endl
#define imp(x) cout<<"Case #"<<x<<": IMPOSSIBLE"<<endl
#define kick_out(x, r) cout<<"Case #"<<x<<": "<<r<<endl
#define testcase(t) int t;cin>>t;while(t--)
#pragma GCC diagnostic ignored "-Wc++11-extensions"
#pragma GCC diagnostic ignored "-Wc++14-extensions"

typedef long long ll; typedef unsigned long long ull; typedef long double ld; typedef pair<ll, ll> p64; typedef vector<ll> vll; typedef vector<bool> vbl; typedef vector<vll> vvll; typedef vector<p64> vp64; typedef map<int, int> m32; typedef map<ll, ll> mll;

const ll LIM = 2e5 + 5;
// MOD = 1e9 + 7;
ll mod;
const ld EPS = 1e-9;
void bandev() {
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
}
ll modInverse(ll a, ll m){ll m0 = m, y = 0, x = 1;if (m == 1){ return 0;}while(a > 1){ ll q = a / m; ll t = m; m = a % m, a = t; t = y; y = x - q * y; x = t; }if (x < 0){ x += m0;}return x;}
ll gcd(ll a, ll b) {if(a==-1){ return b;} if(b==-1) {return a;}if (b == 0) {return a;} return gcd(b, a % b);}
void printBlArr(vector<bool> vec){for(ll i=0; i<vec.size(); i++){cout<<vec[i]<<" ";}cout<<endl;}
void printArr(vll nw){ for (ll i = 0; i < nw.size(); i++){cout << nw[i] << " ";} cout << endl; }
void printMat(vvll mat) {for (ll i = 0 ; i < mat.size() ; i++) {for (ll j = 0; j < mat[i].size() ; j++) {printf("%d ", int(mat[i][j]));}printf("\n");} }
ll sizeDecimal(ll k) {if (k == 0) {return 1;} ll num = 0;while (k > 0) {num++;k /= 10;}return num;}
bool ispal(string& str){for(ll i=0; 2*i<=str.size(); i++){if(str[i]!=str[str.size()-1-i]){return false;}}return true;}
ll sz(vll& vec){if(vec.empty()) {return 0;}return vec.size();}
// ll powsGo(ll n, ll x){if(x==0) {return 1;}ll num = powsGo(n, x/2); if(x%2==1){ return (n*(num*num)%MOD)%MOD; } return (num*num)%MOD;}
vll getArray(ll n){vll nw(n, 0);for(ll i=0; i<n; i++){cin>>nw[i];}return nw;}
vvll getMat(ll n, ll m){vll em(m, 0);vvll mat(n, em);for(ll i=0; i<n; i++){for(ll j=0; j<m; j++){cin>>mat[i][j];}}return mat;}
ll sqrt(ll n){ll st=0,en=n;while(st+1<en){ll mid=(st+en)/2;if(mid*mid <= n) st = mid; else en = mid-1;}return en;}
void printPrs(vp64& prs){for(auto pr : prs) cout<<pr.first<<" "<<pr.second<<endl;}

bool sortNamesFir(const p64 a, const p64 b){
    if(b.first!=a.first) return b.first>a.first;
    return b.second>a.second;
}
bool debug;

void debugPrint(int n){
    if(debug) print(n);
}

// vll testVec;
// vll getDebugVal(ll a, ll b){}

// vll query(ll a, ll b){
//     cout<<"? "<<a+1<<" "<<b+1<<endl;
//     vll nw(b-a+1, 0);
//     if(debug) nw = getDebugVal(a, b);
//     else{
//         for(ll i=a; i<=b; i++){
//             cin>>nw[i-a];
//         }
//     }
//     return nw;
// }

// void final(ll n){
//     cout<<"! "<<n<<endl;
// }
ll segFunc(ll a, ll b){
    return max(a, b);
}
ll getMid(ll s, ll e) { return s + (e -s)/2; }

ll getSumUtil(vector<ll>& st, ll ss, ll se, ll qs, ll qe, ll si)
{
    if (qs <= ss && qe >= se)
        return st[si];

    if (se < qs || ss > qe)
        return 0;

    ll mid = getMid(ss, se);
    return segFunc(getSumUtil(st, ss, mid, qs, qe, 2*si+1),
        getSumUtil(st, mid+1, se, qs, qe, 2*si+2));
}

void updateValueUtil(vector<ll>& st, ll ss, ll se, ll i, ll diff, ll si)
{
    if (i < ss || i > se)
        return;

    st[si] = st[si] + diff;
    if (se != ss)
    {
        ll mid = getMid(ss, se);
        updateValueUtil(st, ss, mid, i, diff, 2*si + 1);
        updateValueUtil(st, mid+1, se, i, diff, 2*si + 2);
    }
}

void updateValue(vector<ll>& arr, vector<ll>& st, ll n, ll i, ll new_val){
    if (i < 0 || i > n-1){
        cout<<"Invalid Input";
        return;
    }
    ll diff = new_val - arr[i];
    arr[i] = new_val;
    updateValueUtil(st, 0, n-1, i, diff, 0);
}

ll constructSTUtil(vector<ll>& arr, ll ss, ll se, vector<ll>& st, ll si){
    if (ss == se){
        st[si] = arr[ss];
        return arr[ss];
    }
    ll mid = getMid(ss, se);
    st[si] = segFunc(constructSTUtil(arr, ss, mid, st, si*2+1),
                constructSTUtil(arr, mid+1, se, st, si*2+2));
    return st[si];
}

ll getSum(vector<ll>& st, ll n, ll qs, ll qe){
    if (qs < 0 || qe > n-1 || qs > qe){
        return 0;
    }
    return getSumUtil(st, 0, n-1, qs, qe, 0);
}

vector<ll> constructST(vector<ll>& arr, ll n){
    ll x = (ll)(ceil(log2(n)));
    ll max_size = 2*(ll)pow(2, x) - 1;
    vector<ll> st(max_size, -1);
    constructSTUtil(arr, 0, n-1, st, 0);
    return st;
}

void showpq(
    priority_queue<int, vector<int>, greater<int> > gq)
{
    priority_queue<int, vector<int>, greater<int> > g = gq;
    while (!g.empty()) {
        cout << '\t' << g.top();
        g.pop();
    }
    cout << '\n';
}
// vll getPrimes(ll n){
// ll k = 1;
//     bitset <10000> bs(3);
//     for (int i = 3; i <= 10000; i += 2) {
//         if (bs[i] == 0) k++;
//         if (k == n) {
//             return i;
//         }
//         if (bs[i] == 0) {
//             for (int j = i * i; j <= 10000; j += i) {
//                 bs[j] = 1;
//             }
//         }
//     }
// }
bool isPrime(ll k) {
    if (k == 1) return false;
    if (k == 2) return true;
    if (k % 2 == 0) return false;
    for (ll i = 3; i * i <= k; i += 2) {
        if (k % i == 0) return false;
    }
    return true;
}

ll mltm(ll a, ll b){
    return (a*b)%mod;
}

ll adm(ll a, ll b){
    if(a+b < 0) return (a+b + mod)%mod;
    return (a+b)%mod;
}

ll powsGo(ll n, ll x){
    if(x==0) {return 1;}
    ll num = powsGo(n, x/2)%mod;
    if(x%2==1){
        return mltm(n, mltm(num,num));
    }
    return mltm(num,num);
}

void run_case(){
    ll n; cin>>n;
    ll m; cin>>m;
    ll res = 0, mul = m%mod, pr = m;
    // m * ((m+1)/2 * powsGo(m, n-2) + m/2 * (5*m/6 * powsGo(m, n-3) + m/6 * ));
    for(ll i=2; i<=n && mul > 0; i++){
        if(isPrime(i)){
            pr /= i;
        }
        ll num = mltm(adm(powsGo(m%mod, n-i+1), - 1), modInverse(adm(m, -1), mod));
        res = adm(res, mltm(mltm(mul, adm(m, -pr)), num));
        mul = mltm(mul, (pr%mod));
    }
    print(res);
    // vll nw = getArray(n);
}

int main(){
    mod = 998244353;
    // srand(time(0));
    debug = true;
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    // bandev();
    ll t = 1;
    cin>>t;
    for(int i=0; i<t; i++){
        run_case();
    }

    return 0;
}

#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
#include "bits/stdc++.h"
using namespace std;
#define fastio ios_base::sync_with_stdio(0);cin.tie(0)
#define pb push_back
// #define mp make_pair
#define forstl(i,v) for(auto &i: v)
#define setbits(x)      __builtin_popcountll(x)
#define zrobits(x)      __builtin_ctzll(x)
// #define mod             1000000007
#define inf             1e18
#define ps(x,y)         fixed<<setprecision(y)<<x
#define getll(n) ll n; cin>>n
#define getstr(n) string n; cin>>n
#define yes cout<<"YES"<<endl
#define no cout<<"NO"<<endl
#define dout if(debug) cout
#define print(x) cout<<x<<endl
#define imp(x) cout<<"Case #"<<x<<": IMPOSSIBLE"<<endl
#define kick_out(x, r) cout<<"Case #"<<x<<": "<<r<<endl
#define testcase(t) int t;cin>>t;while(t--)
#pragma GCC diagnostic ignored "-Wc++11-extensions"
#pragma GCC diagnostic ignored "-Wc++14-extensions"

typedef long long ll; typedef unsigned long long ull; typedef long double ld; typedef pair<ll, ll> p64; typedef vector<ll> vll; typedef vector<bool> vbl; typedef vector<vll> vvll; typedef vector<p64> vp64; typedef map<int, int> m32; typedef map<ll, ll> mll;

const ll LIM = 2e5 + 5;
// MOD = 1e9 + 7;
ll mod;
const ld EPS = 1e-9;
void bandev() {
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
}
ll modInverse(ll a, ll m){ll m0 = m, y = 0, x = 1;if (m == 1){ return 0;}while(a > 1){ ll q = a / m; ll t = m; m = a % m, a = t; t = y; y = x - q * y; x = t; }if (x < 0){ x += m0;}return x;}
ll gcd(ll a, ll b) {if(a==-1){ return b;} if(b==-1) {return a;}if (b == 0) {return a;} return gcd(b, a % b);}
void printBlArr(vector<bool> vec){for(ll i=0; i<vec.size(); i++){cout<<vec[i]<<" ";}cout<<endl;}
void printArr(vll nw){ for (ll i = 0; i < nw.size(); i++){cout << nw[i] << " ";} cout << endl; }
void printMat(vvll mat) {for (ll i = 0 ; i < mat.size() ; i++) {for (ll j = 0; j < mat[i].size() ; j++) {printf("%d ", int(mat[i][j]));}printf("\n");} }
ll sizeDecimal(ll k) {if (k == 0) {return 1;} ll num = 0;while (k > 0) {num++;k /= 10;}return num;}
bool ispal(string& str){for(ll i=0; 2*i<=str.size(); i++){if(str[i]!=str[str.size()-1-i]){return false;}}return true;}
ll sz(vll& vec){if(vec.empty()) {return 0;}return vec.size();}
// ll powsGo(ll n, ll x){if(x==0) {return 1;}ll num = powsGo(n, x/2); if(x%2==1){ return (n*(num*num)%MOD)%MOD; } return (num*num)%MOD;}
vll getArray(ll n){vll nw(n, 0);for(ll i=0; i<n; i++){cin>>nw[i];}return nw;}
vvll getMat(ll n, ll m){vll em(m, 0);vvll mat(n, em);for(ll i=0; i<n; i++){for(ll j=0; j<m; j++){cin>>mat[i][j];}}return mat;}
ll sqrt(ll n){ll st=0,en=n;while(st+1<en){ll mid=(st+en)/2;if(mid*mid <= n) st = mid; else en = mid-1;}return en;}
void printPrs(vp64& prs){for(auto pr : prs) cout<<pr.first<<" "<<pr.second<<endl;}

bool sortNamesFir(const p64 a, const p64 b){
    if(b.first!=a.first) return b.first>a.first;
    return b.second>a.second;
}
bool debug;

void debugPrint(int n){
    if(debug) print(n);
}

// vll testVec;
// vll getDebugVal(ll a, ll b){}

// vll query(ll a, ll b){
//     cout<<"? "<<a+1<<" "<<b+1<<endl;
//     vll nw(b-a+1, 0);
//     if(debug) nw = getDebugVal(a, b);
//     else{
//         for(ll i=a; i<=b; i++){
//             cin>>nw[i-a];
//         }
//     }
//     return nw;
// }

// void final(ll n){
//     cout<<"! "<<n<<endl;
// }
ll segFunc(ll a, ll b){
    return max(a, b);
}
ll getMid(ll s, ll e) { return s + (e -s)/2; }

ll getSumUtil(vector<ll>& st, ll ss, ll se, ll qs, ll qe, ll si)
{
    if (qs <= ss && qe >= se)
        return st[si];

    if (se < qs || ss > qe)
        return 0;

    ll mid = getMid(ss, se);
    return segFunc(getSumUtil(st, ss, mid, qs, qe, 2*si+1),
        getSumUtil(st, mid+1, se, qs, qe, 2*si+2));
}

void updateValueUtil(vector<ll>& st, ll ss, ll se, ll i, ll diff, ll si)
{
    if (i < ss || i > se)
        return;

    st[si] = st[si] + diff;
    if (se != ss)
    {
        ll mid = getMid(ss, se);
        updateValueUtil(st, ss, mid, i, diff, 2*si + 1);
        updateValueUtil(st, mid+1, se, i, diff, 2*si + 2);
    }
}

void updateValue(vector<ll>& arr, vector<ll>& st, ll n, ll i, ll new_val){
    if (i < 0 || i > n-1){
        cout<<"Invalid Input";
        return;
    }
    ll diff = new_val - arr[i];
    arr[i] = new_val;
    updateValueUtil(st, 0, n-1, i, diff, 0);
}

ll constructSTUtil(vector<ll>& arr, ll ss, ll se, vector<ll>& st, ll si){
    if (ss == se){
        st[si] = arr[ss];
        return arr[ss];
    }
    ll mid = getMid(ss, se);
    st[si] = segFunc(constructSTUtil(arr, ss, mid, st, si*2+1),
                constructSTUtil(arr, mid+1, se, st, si*2+2));
    return st[si];
}

ll getSum(vector<ll>& st, ll n, ll qs, ll qe){
    if (qs < 0 || qe > n-1 || qs > qe){
        return 0;
    }
    return getSumUtil(st, 0, n-1, qs, qe, 0);
}

vector<ll> constructST(vector<ll>& arr, ll n){
    ll x = (ll)(ceil(log2(n)));
    ll max_size = 2*(ll)pow(2, x) - 1;
    vector<ll> st(max_size, -1);
    constructSTUtil(arr, 0, n-1, st, 0);
    return st;
}

void showpq(
    priority_queue<int, vector<int>, greater<int> > gq)
{
    priority_queue<int, vector<int>, greater<int> > g = gq;
    while (!g.empty()) {
        cout << '\t' << g.top();
        g.pop();
    }
    cout << '\n';
}
// vll getPrimes(ll n){
// ll k = 1;
//     bitset <10000> bs(3);
//     for (int i = 3; i <= 10000; i += 2) {
//         if (bs[i] == 0) k++;
//         if (k == n) {
//             return i;
//         }
//         if (bs[i] == 0) {
//             for (int j = i * i; j <= 10000; j += i) {
//                 bs[j] = 1;
//             }
//         }
//     }
// }
bool isPrime(ll k) {
    if (k == 1) return false;
    if (k == 2) return true;
    if (k % 2 == 0) return false;
    for (ll i = 3; i * i <= k; i += 2) {
        if (k % i == 0) return false;
    }
    return true;
}

ll powsGo(ll n, ll x){
    if(x==0) {return 1;}
    ll num = powsGo(n, x/2)%mod;
    if(x%2==1){
        return (n*((num*num)%mod))%mod;
    }
    return (num*num)%mod;
}

ll mltm(ll a, ll b){
    return (a*b)%mod;
}

ll adm(ll a, ll b){
    return (a+b+mod)%mod;
}

void run_case(){
    ll n; cin>>n;
    ll m; cin>>m;
    ll res = 0, mul = m%mod, pr = m;
    // m * ((m+1)/2 * powsGo(m, n-2) + m/2 * (5*m/6 * powsGo(m, n-3) + m/6 * ));
    for(ll i=2; i<=n && mul > 0; i++){
        if(isPrime(i)){
            pr /= i;
        }
        ll num = mltm(adm(powsGo(m%mod, n-i+1), - 1), modInverse(adm(m, -1), mod));
        res = adm(res, mltm(mltm(mul, adm(m, -pr)), num));
        mul = mltm(mul, (pr%mod));
    }
    print(res);
    // vll nw = getArray(n);
}

int main(){
    mod = 998244353;
    // srand(time(0));
    debug = true;
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    // bandev();
    ll t = 1;
    // cin>>t;
    for(int i=0; i<t; i++){
        run_case();
    }

    return 0;
}

#include <iostream>
#include <ranges>
#include <algorithm>
#include <numeric>
#include <vector>
#include <array>
#include <set>
#include <map>
#include <bit>
#include <sstream>
#include <list>
#include <stack>

typedef long long integerType;
typedef integerType n;
typedef std::vector<n> v;
typedef std::vector<v> V;
typedef std::set<n> s;
typedef std::multiset<n> S;
typedef std::map<n, n> m;
typedef std::string r;
typedef std::vector<r> R;
typedef std::vector<bool> b;

struct RHEXAOCrocks {
	RHEXAOCrocks() { std::ios_base::sync_with_stdio(false); std::cin.tie(nullptr); }
	template<class T>
	operator T() const { T n; std::cin >> n; return n; }
	std::string operator()() { std::string s; std::cin >> s; return s; }
	v operator()(n n) { v vec(n); for (auto& n : vec) std::cin >> n; return vec; }
	R operator()(integerType n, char del) {
		R vec(n); char ch; std::cin >> ch; vec[0].push_back(ch); int c;
		for (integerType i{}; i < n;++i)
			while ((c = std::cin.get()) != del)
				vec[i].push_back(c);
		return vec;
	}
	V operator()(n r, n c) { V tab(r, v(c)); for (auto& e : tab) for (auto& n : e) std::cin >> n; return tab; }
	template<class T> RHEXAOCrocks& operator[](const T& t) { std::cout << t; return *this; }
	RHEXAOCrocks& operator[](const R& a) { for (auto& e : a) std::cout << e << '\n'; return *this; }
	template<class Ty, template<typename T, typename A = std::allocator<T>> class C> RHEXAOCrocks& operator[](const C<Ty>& c) {
		for (auto Cc{ c.begin() }; Cc != c.end(); std::cout << *Cc << " \n"[++Cc == c.end()]); return *this;
	}
	template<class Ty, template<typename T, typename A = std::allocator<T>> class C> RHEXAOCrocks& operator[](const std::vector<C<Ty>>& c) {
		for (auto& e : c) for (auto E{ e.begin() }; E != e.end(); )std::cout << *E << " \n"[++E == e.end()]; return *this;
	}
}o;

#define i(b,e, ...) for(integerType i : std::views::iota(b,e) __VA_ARGS__)
#define _i(b,e, ...) for(integerType i : std::views::iota(b,e) | std::views::reverse __VA_ARGS__)
#define j(b,e, ...) for(integerType j : std::views::iota(b,e) __VA_ARGS__)
#define _j(b,e, ...) for(integerType j : std::views::iota(b,e) | std::views::reverse __VA_ARGS__)
#define k(b,e, ...) for(integerType k : std::views::iota(b,e) __VA_ARGS__)
#define _k(b,e, ...) for(integerType k : std::views::iota(b,e) | std::views::reverse __VA_ARGS__)
#define l(b,e, ...) for(integerType l : std::views::iota(b,e) __VA_ARGS__)
#define _l(b,e, ...) for(integerType l : std::views::iota(b,e) | std::views::reverse __VA_ARGS__)

#define Aa for(auto A = a.begin(); A != a.end(); ++A)
#define Bb for(auto B = b.begin(); B != b.end(); ++B)
#define Cc for(auto C = c.begin(); C != c.end(); ++C)
#define Dd for(auto D = d.begin(); D != d.end(); ++D)

#define z(a) (n)((a).size())

using namespace std;
namespace ra = ranges;

inline void nwmn(n nw, n& mn) { mn -= ((nw) < mn) * (mn - (nw)); }
inline void nwmx(n nw, n& mx) { mx += ((nw) > mx) * ((nw)-mx); }

int main()
{
	n t{ 1 }, M{ 998244353 };
	while (t--) {
		n l{ o }, m{ o };
		auto pw = [&M](n l, unsigned long long m) {
			n r{ 1 }, p{ l };
			i(0, (n)bit_width(m)) {
				if (m >> i & 1)
					(r *= p) %= M;
				(p *= p) %= M;
			}
			return r;
		};
		auto isprime = [](n m) {
			for (n i{ 2 }; i * i <= m; ++i)
				if (!(m % i))
					return false;
			return true;
		};
		n r{ m }, I{ 1 };
		v a(l + 1);
		i(2, l + 1) {
			n Pw{ pw(m, i) };
			if (I <= m && isprime(i))
				I *= i;
			(r *= m / I) %= M;
			a[i] = (Pw - r + M) % M;
		}
		n tot{};
		i(2, l + 1)
			(tot += a[i]) %= M;
		o[tot];
	}
}

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int P=998244353;
ll n,m;
ll gcd(ll a,ll b)
{
	if(b==0) return a;
	else return gcd(b,a%b);
}
int main()
{
	cin>>n>>m;
	ll res=0;
	ll sum=1;//���쳤��Ϊiʱ ���������
	ll fg=1;
	ll k=1;//����һ�����ʵ���
	for(ll i=1;i<=n;i++)
	{
		sum=(sum*(m%P))%P;
		if(gcd(i,k)==1)
		{
			if(fg) k*=i;
		}
		if(k>m) fg=0; //�����k���ܴ���m
		fg=(fg*(m/k)%P)%P;
		res=(res+sum)%P;
		res=(res-fg+P)%P;//�ݳ�
	}
	cout<<res<<endl;
}

#include <bits/stdc++.h>
#define ll long long
#define pb push_back

using namespace std;

ll N = 998244353;

ll mpow(ll base, ll n)
{
    base %= N;
    if(n==0) return 1;
    ll x = mpow(base, n/2);
    if(n%2==0) return (x*x)%N;
    else return (((x*x)%N)*base)%N;
}

ll gcd(ll x, ll y)
{
    while(y>0)
    {
        ll r = x%y;
        x = y;
        y = r;
    }
    return x;
}
int main()
{
    ios_base::sync_with_stdio(false);
	cin.tie();
	cout.tie();

    vector<ll> a(36, 1);
    for(int i=1; i<36; i++)
    {
        if(gcd(a[i-1], i+1)==1) a[i] = a[i-1]*(i+1);
        else a[i] = a[i-1];
    }
    //for(ll x: a) cout << x << endl;
    ll n, m;
    cin >> n >> m;

    ll ans;
    if(m%N==1) ans = n;
    else
    {
        ans = (mpow(m, n+1)+N-1)%N;
        ans *= mpow(m-1, N-2);
        ans--;
        ans %= N;
    }

    ll x = m/a[35];
    for(int i=34; i>=0; i--)
    {
        //cout << i << endl;
        x++;
        x *= (m/a[i]%N);
        x %= N;
    }
    cout << ans << " " << x << endl;
    cout << (ans - x + N) % N;
}

//C:\Users\tbziy\Documents\GitHub\cfeditor\Solution1.cpp
// D. Counting Arrays
// time limit per test2 seconds
// memory limit per test512 megabytes
// inputstandard input
// outputstandard output
// Consider an array a of length n with elements numbered from 1 to n. It is possible to remove the i-th element of a if gcd(ai,i)=1, where gcd denotes the greatest common divisor. After an element is removed, the elements to the right are shifted to the left by one position.

// An array b with n integers such that 1≤bi≤n−i+1 is a removal sequence for the array a if it is possible to remove all elements of a, if you remove the b1-th element, then the b2-th, ..., then the bn-th element. For example, let a=[42,314]:

// [1,1] is a removal sequence: when you remove the 1-st element of the array, the condition gcd(42,1)=1 holds, and the array becomes [314]; when you remove the 1-st element again, the condition gcd(314,1)=1 holds, and the array becomes empty.
// [2,1] is not a removal sequence: when you try to remove the 2-nd element, the condition gcd(314,2)=1 is false.
// An array is ambiguous if it has at least two removal sequences. For example, the array [1,2,5] is ambiguous: it has removal sequences [3,1,1] and [1,2,1]. The array [42,314] is not ambiguous: the only removal sequence it has is [1,1].

// You are given two integers n and m. You have to calculate the number of ambiguous arrays a such that the length of a is from 1 to n and each ai is an integer from 1 to m.

// Input
// The only line of the input contains two integers n and m (2≤n≤3⋅105; 1≤m≤1012).

// Output
// Print one integer — the number of ambiguous arrays a such that the length of a is from 1 to n and each ai is an integer from 1 to m. Since the answer can be very large, print it modulo 998244353.

// Examples
// inputCopy
// 2 3
// outputCopy
// 6
// inputCopy
// 4 2
// outputCopy
// 26
// inputCopy
// 4 6
// outputCopy
// 1494
// inputCopy
// 1337 424242424242
// outputCopy
// 119112628

#include <bits/stdc++.h>

using namespace std;

// Using long long instead of ll to avoid overflow
// defines to reduce typing
#define ll long long
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define all(x) (x).begin(), (x).end()
#define rev(x) (x).rbegin(), (x).rend()
#define sz(x) (ll)(x).size()
#define UMP unordered_map
#define UST unordered_set

// typedefs to reduce typing
typedef vector<ll> vi;
typedef pair<ll, ll> pi;

//思路:
//计算出所有序列的个数：
//total = m^1 + m^2 + m^3 + ... + m^n
//计算需要减掉的不合法序列的个数：
//假设P为存储所有质数的数组
//total2 = sum( m / (p1 * p2 * …… * pk ) ) 其中p1,p2,……,pk表示不超过i的所有质数,0<=i<=n。
//答案为total - total2

//计算不超过n的所有质数
//使用欧拉筛
vector<ll> getPrime(ll n)
{
    vector<ll> prime;
    vector<bool> isPrime(n + 1, true);
    for (ll i = 2; i <= n; i++)
    {
        if (isPrime[i])
        {
            prime.push_back(i);
        }
        for (ll j = 0; j < prime.size() && i * prime[j] <= n; j++)
        {
            isPrime[i * prime[j]] = false;
            if (i % prime[j] == 0)
            {
                break;
            }
        }
    }
    return prime;
}

const ll mod = 998244353;

ll fast_pow(ll a, ll b)
{
    ll res = 1;
    while (b)
    {
        if (b & 1)
        {
            res = res * a % mod;
        }
        a = a * a % mod;
        b >>= 1;
    }
    return res;
}

//main function
int main()
{
    //input
    ll n, m;
    cin >> n >> m;
    //计算不超过n的所有质数
    vector<ll> prime = getPrime(n);
    //计算total
    ll total = 0;
    ll cur = 1;
    for (ll i = 1; i <= n; i++)
    {
        cur = cur * m % mod;
        total = (total + cur) % mod;
    }
    //计算total2
    ll total2 = 0;
    //指向当前不超过i的最大质数
    ll p_idx = 0;
    cur = 1;
    ll cur2 = 1;
    for (ll i = 1; i <= n; i++)
    {
        //计算不超过i的所有质数
        while (p_idx < prime.size() && prime[p_idx] <= i)
        {
            cur = cur * prime[p_idx];
            if(cur > m){
                goto end;
            }
            p_idx++;
        }
        int tmp = m / cur;
        cur2 *= tmp;
        //计算m / (p1 * p2 * …… * pk)
        total2 += cur2;
    }
    end:;
    //计算答案
    ll ans = (total - total2 + mod) % mod;
    //output
    //cout << total <<" "<< total2 <<" "<< ans << endl;
    cout<<ans<<endl;
    return 0;
}

#include <bits/stdc++.h>
using namespace std;
namespace fastIO{
	#define BUF_SIZE 100000
	#define OUT_SIZE 100000
	//fread->read
	bool IOerror=0;
	//inline char nc(){char ch=getchar();if(ch==-1)IOerror=1;return ch;}
	inline char nc(){
		static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;
		if(p1==pend){
			p1=buf;pend=buf+fread(buf,1,BUF_SIZE,stdin);
			if(pend==p1){IOerror=1;return -1;}
		}
		return *p1++;
	}
	inline bool blank(char ch){return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';}
	template<class T> inline bool read(T &x){
		bool sign=0;char ch=nc();x=0;
		for(;blank(ch);ch=nc());
		if(IOerror)return false;
		if(ch=='-')sign=1,ch=nc();
		for(;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
		if(sign)x=-x;
		return true;
	}
	inline bool read(double &x){
		bool sign=0;char ch=nc();x=0;
		for(;blank(ch);ch=nc());
		if(IOerror)return false;
		if(ch=='-')sign=1,ch=nc();
		for(;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
		if(ch=='.'){
			double tmp=1; ch=nc();
			for(;ch>='0'&&ch<='9';ch=nc())tmp/=10.0,x+=tmp*(ch-'0');
		}
		if(sign)x=-x;
		return true;
	}
	inline bool read(char *s){
		char ch=nc();
		for(;blank(ch);ch=nc());
		if(IOerror)return false;
		for(;!blank(ch)&&!IOerror;ch=nc())*s++=ch;
		*s=0;
		return true;
	}
	inline bool read_line(char *s){
		char ch=nc();
		for(;blank(ch);ch=nc());
		if(IOerror)return false;
		for(;ch!='\n'&&!IOerror;ch=nc())*s++=ch;
		*s=0;
		return true;
	}
	inline bool read(char &c){
		for(c=nc();blank(c);c=nc());
		if(IOerror){c=-1;return false;}
		return true;
	}
	template<class T,class... U>bool read(T& h,U&... t){return read(h)&&read(t...);}
	#undef OUT_SIZE
	#undef BUF_SIZE
};
using namespace fastIO;
/************* debug begin *************/
string to_string(string s){return '"'+s+'"';}
string to_string(const char* s){return to_string((string)s);}
string to_string(const bool& b){return(b?"true":"false");}
template<class T>string to_string(T x){ostringstream sout;sout<<x;return sout.str();}
template<class A,class B>string to_string(pair<A,B> p){return "("+to_string(p.first)+", "+to_string(p.second)+")";}
template<class A>string to_string(const vector<A> v){
	int f=1;string res="{";for(const auto x:v){if(!f)res+= ", ";f=0;res+=to_string(x);}res+="}";
	return res;
}
void debug_out(){puts("");}
template<class T,class... U>void debug_out(const T& h,const U&... t){cout<<" "<<to_string(h);debug_out(t...);}
#ifdef tokitsukaze
#define debug(...) cout<<"["<<#__VA_ARGS__<<"]:",debug_out(__VA_ARGS__);
#else
#define debug(...) 233;
#endif
/*************  debug end  *************/
#define mem(a,b) memset((a),(b),sizeof(a))
#define MP make_pair
#define pb push_back
#define fi first
#define se second
#define sz(x) (int)x.size()
#define all(x) x.begin(),x.end()
#define sqr(x) (x)*(x)
using namespace __gnu_cxx;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
typedef pair<int,ll> PIL;
typedef pair<ll,int> PLI;
typedef vector<int> VI;
typedef vector<ll> VL;
typedef vector<PII > VPII;
/************* define end  *************/
void read(int *x,int l,int r){for(int i=l;i<=r;i++) read(x[i]);}
void read(ll *x,int l,int r){for(int i=l;i<=r;i++) read(x[i]);}
void read(double *x,int l,int r){for(int i=l;i<=r;i++) read(x[i]);}
void println(VI x){for(int i=0;i<sz(x);i++) printf("%d%c",x[i]," \n"[i==sz(x)-1]);}
void println(VL x){for(int i=0;i<sz(x);i++) printf("%lld%c",x[i]," \n"[i==sz(x)-1]);}
void println(int *x,int l,int r){for(int i=l;i<=r;i++) printf("%d%c",x[i]," \n"[i==r]);}
void println(ll *x,int l,int r){for(int i=l;i<=r;i++) printf("%lld%c",x[i]," \n"[i==r]);}
/*************** IO end  ***************/
void assert_lr(ll x,ll l,ll r) {assert(x>=l&&x<=r);};
void go();
int main(){
	#ifdef tokitsukaze
		freopen("TEST.txt","r",stdin);
	#endif
	go();return 0;
}
const int INF=0x3f3f3f3f;
const ll LLINF=0x3f3f3f3f3f3f3f3fLL;
const double PI=acos(-1.0);
const double eps=1e-6;
const int MAX=3e5+10;
const ll mod=998244353;
/*********************************  head  *********************************/
ll pow2(ll a,ll b)
{
	ll res=1;
	while(b>0)
	{
		if(b&1) res=res*a%mod;
		a=a*a%mod;
		b>>=1;
	}
	return res;
}
//x is a prime if prime[x]==x(x>=2)
int p[MAX],tot,prime[MAX];
void init(int n)
{
	int i,j;
	tot=0;
	mem(prime,0);
	prime[1]=1;
	for(i=2;i<=n;i++)
	{
		if(!prime[i]) prime[i]=p[tot++]=i;
        for(j=0;j<tot&&p[j]*i<=n;j++)
		{
			prime[i*p[j]]=p[j];
			if(i%p[j]==0) break;
		}
	}
}
VI res;
void go()
{
	int n,i;
	ll ans,bs,now,m,res;
	init(MAX-10);
	while(read(n,m))
	{
		now=m%mod;
		ans=m%mod;
		res=0;
		bs=1;
		for(i=2;;i++)
		{
			if(prime[i]==i) bs*=i;
			if(bs>m) break;
	//		debug(i,bs)
			now=now*((m/bs)%mod)%mod;
			ans=(ans+now)%mod;
		}
	//	debug(ans)
		ans=-ans;
		bs=1;
		for(i=1;i<=n;i++)
		{
			bs=bs*(m%mod)%mod;
			ans=(ans+bs)%mod;
		}
		printf("%lld\n",(ans+mod)%mod);
	}
}

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=3e5+100,mod=998244353;
ll qpow(ll x,int y){
	x%=mod;
	ll ans=1;
	while(y){
		if(y&1) ans=ans*x%mod;
		x=x*x%mod;y>>=1;
	}
	return ans;
}
ll gcd(ll x,ll y){
	return y?gcd(y,x%y):x;
}
ll lcm(ll x,ll y){
	return 1ll*x/gcd(x,y)*y;
}
int n;
ll m,L[1010];
int main(){
	scanf("%d%lld",&n,&m);
	L[1]=1;
	int lim;
	for(lim=2;;lim++){
		if(gcd(L[lim-1],lim)==1) L[lim]=L[lim-1]*lim;
		else L[lim]=L[lim-1];
		if(L[lim]>m) break;
	}
	ll ans=1ll*((qpow(m,n+1)-m+mod)%mod)*qpow(m-1,mod-2)%mod;
	for(int i=1;i<lim;i++){
		ll now=1;
		for(int j=1;j<=i;j++) now=now*((m/L[j])%mod)%mod;
		ans=(ans-now+mod)%mod;
	}
	printf("%lld\n",ans);
	return 0;
}

#include <vector>
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;

#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,a,n) for(int i=n;i>=a;i--)
#define fi first
#define se second
typedef pair<int,int> PII;
typedef unsigned long long ull;
typedef double de;
typedef long long ll;

const int N = 3e5+10, M = 1 << 15;
const ll md = 998244353;
ll gcd(ll a ,ll b) {return b?gcd(b,a%b):a;}
ll ceil(ll a,ll b) {return a/b+(a%b>0);}

ll sum[N],res[N];
bool st[N];
int cnt;
int prime[N];
void init()
{
    for(int i=2;i<N;i++)
    {
        if(!st[i]) prime[cnt++]=i;
        for(int j=0;prime[j]<=N/i;j++)
        {
            st[prime[j]*i]=true;
            if(i%prime[j]==0) break;
        }
    }
}

ll lcm(ll a,ll b)
{
    return a*b/gcd(a,b);
}

inline void solve()
{
    ll n,m;
    cin >> n >> m;
    ll lc=1;
    sum[1]=m%md;
    res[1]=m%md;
    for(int i=2;i<=n;i++)
    {
        if(!st[i]) lc=lcm(lc,i);
        ll cnt=m/lc;
        res[i]=res[i-1]%md*cnt%md;
        sum[i]=(sum[i-1]*m)%md;
    }
    ll ans=0;
    for(int i=1;i<=n;i++)
    {
        ans=((ans+sum[i]-res[i])%md+md)%md;
    }
    printf("%lld\n",ans);
}
int main()
{
	cin.tie(0);
	cout.tie(0);
    int t=1;
    init();
    //cin >> t;
    rep(_,1,t) solve();
	return 0;
}

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll Mod=998244353;
ll n,m,ans,Ans,Lcm=1,aLl;
bool ok;
ll gcd(ll a,ll b){
	if(!b) return a;
	return gcd(b,a%b);
}
ll ksm(ll a,ll b){
	ll ans=1;
	while(b){
		if(b&1) ans=ans*a%Mod;
		a=a*a%Mod,b>>=1;
	}
	return ans;
}
int main(){
	scanf("%lld%lld",&n,&m);
	aLl=m,Ans=m,ans=m;
	for(int i=2;i<=n;i++){
		Lcm=Lcm*i/gcd(Lcm,i);
		if(Lcm>m) ok=1;
		if(ok) ans=ans*0%Mod;
		else ans=ans*(m/Lcm)%Mod;
		Ans=(Ans+ans)%Mod;
		aLl=(aLl+ksm(m,i))%Mod;
	}
	printf("%lld\n",(aLl-Ans+Mod)%Mod);
	return 0;
}

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define Endl endl
#define float double
#define ll long long
#define endl '\n'
#define gc getchar_unlocked
#define fo(i,n) for(int i=0;i<n;i++)
#define Fo(i,k,n) for(int i=k;k<n?i<n:i>n;k<n?i+=1:i-=1)
#define deb(x) cout << #x << "=" << x << endl
#define deb2(x, y) cout << #x << "=" << x << "," << #y << "=" << y << endl
#define pb push_back
#define mp make_pair
#define F first
#define S second
#define all(x) x.begin(), x.end()
#define in(j) int j = 0 ; cin>> j
#define sin(s) string s ; cin>>s
#define clr(x) memset(x, 0, sizeof(x))
#define mem(x) memset(x, 0, sizeof(x))
#define sorta(x) sort(all(x))
#define sortd(x) sort(all(x), greater<>())
#define popcount(x) __builtin_popcountll(x)
#define parity(x) __builtin_parityll(x)
#define trail_zero(x) __builtin_ctzll(x)
#define tr(it, a) for(auto it = a.begin(); it != a.end(); it++)
#define PI 3.1415926535897932384626
#define ed(n) vector<int> *edges = new vector<int>[n] ;
#define take(n)  in(n) ; vi g(n) ; fo(i , n)cin>>g[i] ;
#define yes cout<<"YES"<<endl ;
#define no cout<<"NO"<<endl ;

const int mod = 1'000'000'007;
const int N = 3e5, M = N;

mt19937_64 rang(chrono::high_resolution_clock::now().time_since_epoch().count());
int rng(int lim) {uniform_int_distribution<int> uid(0,lim-1); return uid(rang);}

/*-----------------------------------------------------------------------------------------------------*/
typedef pair<int, int> pii; typedef vector<int> vi; typedef vector<pii> vpii;
typedef vector<vi> vvi; typedef priority_queue<int> pqi; typedef map<int,int> mii ;
int mpow(int base, int exp,int m = mod) {base %= m;int result = 1;while (exp > 0) {if (exp & 1)
{result = ((ll)result * base) % m;}base = ((ll)base * base) % m;exp >>= 1;}return result;}
vector<ll> sieve(int n) {int*arr = new int[n + 1](); vector<ll> vect; for (int i = 2; i <= n; i++)
{if (arr[i] == 0) {vect.push_back(i); for (int j = 2 * i; j <= n; j += i)arr[j] = 1;} }return vect;}
void extendgcd(ll a, ll b, ll*v) {if (b == 0) {v[0] = 1; v[1] = 10; v[2] = a; return ;}
extendgcd(b, a % b, v); ll x = v[1]; v[1] = v[0] - v[1] * (a / b); v[0] = x; return;}
ll mod_add(ll a, ll b, ll m = mod) {a = a % m; b = b % m; return (((a + b) % m) + m) % m;}
ll mod_mul(ll a, ll b, ll m = mod) {a = a % m; b = b % m; return (((a * b) % m) + m) % m;}
ll mod_sub(ll a, ll b, ll m = mod) {a = a % m; b = b % m; return (((a - b) % m) + m) % m;}
ll mminv(ll a, ll b) {ll arr[3]; extendgcd(a, b, arr); return mod_add(arr[0], 0, b);}
ll mminvprime(ll a, ll b) {return mpow(a, b - 2, b);}
ll mod_div(ll a, ll b, ll m = mod) {a = a % m; b = b % m; return (mod_mul(a, mminvprime(b, m), m)+m)%m;}
int fact(int n, int m = mod){if (n>=m){return 0;}int r=1;for(int i=1; i <= n; i++){r=(r*i)%m;}return r;}
vi prime_fac(int n){vector<int> v ; while (n % 2 == 0){v.pb(2) ; n = n/2;}for (int i = 3; i <= sqrt(n);
i = i + 2){while (n % i == 0){v.pb(i) ; n = n/i;}}if (n > 2){v.pb(n) ; } return v ; }
bool prime(int n){if (n <= 1){return false;}if (n <= 3){return true;}if (n % 2 == 0 || n % 3 == 0){
return false;}for(int i=5; i*i<=n;i=i+6){if(n%i ==0 || n%(i+2)==0)return false;}return true;}
/*-----------------------------------------------------------------------------------------------------*/
/*
#1 popcount(x) -> counts set bits
#2 parity(x) -> Returns 1 if the number has odd number of set bits
#3 trail_zero(x) -> trailing number of zeros
#4 __lg(x) -> log base 2
#5 prime_fac-> prime factorization with repeated primes
#6 fact-> factorial
*/
bool compare(pair<int,int> a, pair<int, int> b)
{
   return (a.S < b.S);
}
//================================================code================================================//

const int MOD = 998244353  ;

void solve() {

	in(n) ; in(m) ;
	  vector<bool> p(n + 1, true);
  for (int i = 2; i <= n; i++){
    if (p[i]){
      for (int j = i * 2; j <= n; j += i){
        p[j] = false;
      }
    }
  }
int ans = 0;
Fo(i,1,n+1){
    ans += mpow(m,i);
  }
  ans %= MOD;
int P = 1;int L = 1;
Fo(i,1,n+1){
    if (p[i]){
      L *= i;
      if (L > m){
        break;
      }
    }
    P *= m / L % MOD;
    P %= MOD;
    ans += MOD - P;
  }
  ans %= MOD;
  cout << ans << endl;

}

int32_t main() {
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
	ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
   srand(chrono::high_resolution_clock::now().time_since_epoch().count());

	int t = 1;

	while(t--) {
	  solve();
	}

	return 0;
}

#include<bits/stdc++.h>
using namespace std;

#define int int64_t

const int mod = 998244353;

int powmod(int x, int y) {
	x %= mod;
	int ans = 1;
	while(y)
	{
		if(y & 1) ans = ans * x % mod;
		x = x * x % mod;
		y >>= 1;
	}
	return ans;
}

int gcd(int x, int y) {
    if (!x) return y;
    if (!y) return x;
    return gcd(y, x%y);
}

int32_t main(){
    int n, m;
	cin >> n >> m;
	int ans = 0;
	for(int i=2;i<=n;i++) ans = (ans + powmod(m, i)) % mod;

	int x = 1; /* product of all primes leq 1 */
	int cnt = 1;
	int res = 0;
	for (int i=2;i<=n;i++) {
		if (gcd(x, i) == 1){
			if (x <= m) x *= i;
			else break;
		}

		cnt = cnt * ((m / x) % mod) % mod;
		res += cnt;
	}
	cout << ans - res << endl;
}

#include <bits/stdc++.h>
using namespace std;
#ifdef LOCAL
#include "debugger.h"
#else
#define dbg(...) 5
#endif

#define ll long long

namespace Math
{
	const long long MOD = (long long)998244353;
	const int SIZE = (int) 3e5 + 5;

	template <typename T> T gcd(T a, T b)
	{
		if (a > b)
			swap(a, b);
		return (a > 0 ? __gcd(a, b) : b);
	}

	template <typename T> T lcm(T a, T b)
	{
		return (a * b) / gcd(a, b);
	}

	inline long long add(long long a, long long b)
	{
		long long res = a + b;
		while (res >= MOD)
			res -= MOD;
		return res;
	}

	inline long long sub(long long a, long long b)
	{
		long long res = a - b;
		while (res < 0)
			res += MOD;
		return res;
	}

	inline long long mult(long long a, long long b)
	{
		return (a * b) % MOD;
	}

	long long fxp(long long x, long long p)
	{
		if (p == 0) return 1LL;
		long long res = fxp(x, p / 2);
		res *= res;
		res %= MOD;;

		if (p & 1) res *= x;
		res %= MOD;
		return res;
	}

	/*
	 * Say ax+by = gcd(a,b)
	 * Given a,b, extended euclid calculates the value of gcd(a,b) while simultaneously
	 * finding out the coefficients for a and b, that is, x and y respectively.
	 */
	long long extendedEuclid(long long a, long long b, long long& x, long long& y)
	{
		if (b == 0)
		{
			x = 1;
			y = 0;
			return a;
		}
		long long x1, y1;
		long long g = extendedEuclid(b, a % b, x1, y1);
		x = y1;
		y = x1 - y1 * (a / b);
		return g;
	}

	long long modinv(long long x)
	{
		long long x1, y1, z = 0;
		long long g = extendedEuclid(x, MOD, x1, y1);
		return (g > 1 ? -1 : sub(x1, z));
	}

	long long factorial[SIZE];
	long long inverseFactorial[SIZE];

	// TODO: ALWAYS INITIALIZE precompute() before using any functions in this namespace
	void precompute()
	{
		factorial[0] = 1;
		for (int i = 1; i < SIZE; i++)
		{
			factorial[i] = mult(factorial[i - 1], i);
		}
		inverseFactorial[SIZE - 1] = modinv(factorial[SIZE - 1]);
		for (int i = SIZE - 2; i >= 0; i--)
		{
			inverseFactorial[i] = mult(inverseFactorial[i + 1], i + 1);
		}
	}

	long long nCr(long long n, long long r)
	{
		return mult(mult(inverseFactorial[r], inverseFactorial[n - r]), factorial[n]);
	}
}

using namespace Math;

const int MAXN = 3e5+5;
// const ll MOD = 998244353;
ll pp[MAXN];
ll dp[MAXN];
// ll fact[MAXN];

// ll fxp(ll x,ll p)
// {
// 	if(p == 0) return 1;
// 	ll res = fxp(x,p/2);
// 	res *= res;
// 	res %= MOD;
// 	if(p%2 == 0)
// 	{
// 		res *= x;
// 		res %= MOD;
// 	}
// 	return res;
// }

// ll

void solve()
{
	ll n,m;
	cin >> n >> m;
	// ll t1 = fxp(m,n);
	// t1 *= fact[n];
	// t1 %= MOD;
	// ll t2 = fxp(m,n);
	// ll t3 = fact[n];
	// t1 *= t2;
	// t1 %= MOD;
	// ll ans =

	ll ans = 0;
	dp[0] = 1;
	// dp2[0] = 0;
	for(int i = 1; i <= n; i++)
	{
		// dp[i] = m/i;
		// dp[i] *= dp[i-1];
		// dp[i] %= MOD;
		ll t1 = fxp(m,i);
		ll tomult = (m/pp[i])%MOD;//(m*modinv(pp[i]))%MOD;
		dp[i] = (dp[i-1]*tomult)%MOD;
		// dp[i] = (((dp[i-1]*m)%MOD)*modinv(pp[i]))%MOD;
		// ll t2 = (m*modinv(pp[i]))%MOD;
		// t1 *= factorial[i];
		// ll t2 = m;//fxp(m,i);
		// // t1 = sub(t1,t2);
		// ll t3 = inverseFactorial[i];
		// t2 = mult(t2,t3);
		// dbg(i,t1,t2,t3);
		// ll toadd = mult(t1,t3);
		ll toadd = sub(t1,dp[i]);
		ans = add(ans,toadd);
	}
	cout << ans << "\n";
}

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	precompute();
	auto is_prime = [&](int x)
	{
		for(int i = 2; i*i <= x; i++)
		{
			if(x%i == 0) return false;
		}
		return true;
	};
	pp[0] = 1;
	for(int i = 1; i < MAXN; i++)
	{
		pp[i] = pp[i-1];
		if(is_prime(i)) pp[i] *= i;
		pp[i] %= MOD;
	}
	// fact[0] = 1;
	// for(int i = 1; i < MAXN; i++)
	// {
	// 	fact[i] = (fact[i-1]*i)%MOD;
	// }
	int test = 1;
	// cin >> test;
	while(test--) solve();
	return 0;
}

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 10;
const ll mod = 998244353;

ll n, a[maxn], m, p = 998244353;
ll not_prime[maxn], prime[maxn], cnt, phi[maxn];

ll ksm(ll x, ll y){
	ll res = 1;
	while(y){
		if(y&1) res = res * x % p;
		y >>= 1;
		x = x * x % p;
	}
	return res;
}

ll mul(ll x, ll y){
	ll res = 0;
	while(y){
		if(y&1) res = (res + x) % p;
		y >>= 1;
		x = (x + x ) % p;
	}
	return res;
}

ll inv(ll x){
	return ksm(x, p-2);
}

void solve(){
    cin >> n >>m;
    ll ans = 0, tmp = 1, tt = 1;

    for(ll i = 1, base = m; i <= n; i++, base = mul(base, m)){
if(!not_prime[i] && tt <= m)tt = tt * i;
tmp = (m / tt * tmp) % mod;
        ans = (ans + base - tmp + mod) % mod;
    }
    cout << (ans + mod) % mod << '\n';
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
phi[1] = 1;
    for(int i = 2; i < maxn; i++){
        if(!not_prime[i]){
            prime[cnt++] = i;
            phi[i] = i-1;
        }
        for(int j = 0; j < cnt && prime[j] * i < maxn; j++){
            not_prime[prime[j] * i] = 1;
            if(i % prime[j] == 0){
                phi[prime[j] * i] = phi[i] * prime[j];
                break;
            }
            phi[prime[j] * i] = phi[i] * (prime[j] - 1);
        }
    }
    ll T = 1;
    while(T--){
        solve();
    }
    return 0;
}

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll mod = 998244353;

ll power(ll a, ll b){
    if(b==0) return 1;
    if(b==1) return a;
    ll x = power(a, b/2) % mod;
    if(b % 2 == 0) return (x * x) % mod;
    return (((x * x) % mod) * (a % mod)) % mod;
}

ll find_total(ll m, ll n){
    ll num = m % mod;
    ll p = power(m, n) % mod;
    p = (p - 1 + mod) % mod;
    num = (num * p) % mod;

    ll den = m - 1;
    ll den_mod = power(den, mod - 2) % mod;
    ll res = ((num % mod) * (den_mod % mod)) % mod;
    return res % mod;
}

ll isPrime(ll x){
    if(x<2) return 0;
    for(ll i=2; i*i <= x; i++){
        if(x%i==0) return 0;
    }
    return 1;
}

int main(){
    int t;
    // cin >> t;
    t = 1;
    while(t--){
        ll n, m;
        cin >> n >> m;
        // ll total = find_total(m, n);
        // ll ambi = find_ambi(m, n);
        // cout << (total - ambi + mod) % mod << "\n";
        ll total = find_total(m, n);
        ll prod_of_primes = 1;
        ll prod = 1;
        for(ll i=1; i<=n; i++){
            if(prod_of_primes > m) continue;
            if(isPrime(i)) prod_of_primes *= i;
            prod = (prod * ((m / prod_of_primes) % mod)) % mod;
            total = (total - prod + mod) % mod;
        }
        cout << total << "\n";
    }
    return 0;
}

/*
    Title:
    Code:
    Algorithm:
    Sol:
*/
#include <bits/stdc++.h>

#define ll long long
#define re register
#define Mod 998244353

using namespace std;
const int maxn = 3e5 + 5;

inline ll read(){
    int s = 0, w = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
    while(ch >= '0' && ch <= '9'){s = (s << 1) + (s << 3) + (ch ^ 48); ch = getchar();}
    return s * w;
}

ll n, m, ans, tmp, cnt;
inline void Mul(ll &a, ll b) { a = a * b % Mod;}
inline void Add(ll &a, ll b) { a += b; if (a >= Mod) a -= Mod; }

ll quickpow(ll a, ll b){
    ll res = 1;
    while(b){
        if(b & 1)   res = res * a % Mod;
        a = a * a % Mod;
        b >>= 1;
    }
    return res;
}

bool prime(int x)
{
    for(int i = 2; i * 1ll * i <= x; i++)
        if(x % i == 0)
            return false;
    return true;
}

int main() {
    n = read(), m = read();
    for(re int i = 1; i <= n; i++)
        Add(ans, quickpow(m % Mod, i));
    cnt = tmp = 1;
    for(re int i = 1; i <= n; i++){
        if(tmp > m) break;
        if(prime(i)) tmp = tmp * i;
        Mul(cnt, (m / tmp) % Mod);
        ans = (ans - cnt + Mod) % Mod;
    }
    printf("%lld\n", ans);

	return 0;
}

#include <bits/stdc++.h>

using namespace std;
const int N = 3e5+ 20;
typedef long long ll;
ll P = 998244353;
int primes[N], cnt =0;     // primes[]存储所有素数
bool st[N];         // st[x]存储x是否被筛掉

void get_primes(int n)
{
    for (int i = 2; i <= n; i ++ )
    {
        if (st[i]) continue;
        primes[cnt ++ ] = i;
        for (int j = i + i; j <= n; j += i)
            st[j] = true;
    }
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(NULL); cout.tie(NULL);

	ll n,m;
	cin >> n >> m;
	get_primes(n+2);
	ll num = 0;
	ll ans = 0;
	ll d = 1;
	ll cn = 1;
	ll mul = 1;
	for(ll i = 1; i <= n;i++)
	{
		if(!st[i]) cn *= i;
		if(cn > m) break;
		mul *= (m/cn %P);
		num += mul;
	}
	for(int i = 1; i <= n;i++)
	{
		d *= m;
		ans += d;
		ans  %= P;
		d %= P;
	}

	cout << ans - num << endl;
}

#include <algorithm>
#include <iostream>
#include <map>
#include <numeric>
#include <set>
#include <string>
#include <utility>
#include <vector>

using namespace std;

#define int long long

constexpr int M = 998244353;

class modint {

    int v;

    public:
    modint(int v = 0) : v{v % M} {
        if (this->v < 0) {
            this->v += M;
        }
    }

    friend ostream& operator<<(ostream& o, const modint& a) {
        return o << a.v;
    }

    friend istream& operator>>(istream& i, modint& b) {
        return i >> b.v;
    }

    friend modint pow(const modint& a, int b) {
        modint ans = 1;
        modint acc = a;
        while (b > 0) {
            if (b & 1) {
                ans *= acc;
            }
            b >>= 1;
            acc *= acc;
        }
        return ans;
    }

    modint operator+(const modint& a) {
        return v + a.v;
    }

    modint& operator+=(const modint& a) {
        v += a.v;
        v %= M;
        return *this;
    }

    modint operator- (const modint& a) {
        return v - a.v;
    }

    modint& operator-=(const modint& a) {
        v -= a.v;
        v %= M;
        if (v < 0) {
            v += M;
        }
        return *this;
    }

    modint operator* (const modint& a) {
        return v * a.v;
    }

    modint& operator*=(const modint& a) {
        v *= a.v;
        v %= M;
        return *this;
    }

    modint operator/(const modint& a) {
        modint res = v;
        return res *= pow(a, M - 2);
    }

    modint operator/=(const modint& a) {
        return *this *= pow(a, M - 2);
    }

    bool operator<(const modint& a) {
        return v < a.v;
    }

    bool operator<=(const modint& a) {
        return v <= a.v;
    }

    bool operator>(const modint& a) {
        return v > a.v;
    }

    bool operator >=(const modint& a) {
        return v >= a.v;
    }

    bool operator ==(const modint& a) {
        return v == a.v;
    }

    explicit operator int() {
        return v;
    }
};

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, m;
    cin >> n >> m;
    modint total = m;
    if (m != 1) {
        total = (pow(modint(m), n + 1) - m) / (m - 1);
    }
    modint inv = m;
    int foo = 1;
    modint goo = m;
    for (int i = 2; i <= n; ++i) {
        if (foo <= m && gcd((int)foo, i) == 1) {
            foo *= i;
        }
        goo *= m / (int)foo;
        inv += goo;
    }
    cout << total - inv << '\n';
}

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define min(a,b) ((a<b)?a:b)
#define ini(n) ll n;cin>>n
#define sti(n) string n;cin>>n
#define arri(arr,s,e) for (ll i = (s); i <= (e); i++)cin>>arr[i]
#define frange(i,s,e) for (ll i = (s); i <= (e); i++)
#define f first
#define s second
#define yes cout<<"YES"<<endl
#define no cout<<"NO"<<endl

ll mod=998244353;

ll powmod(ll n,ll p,ll m){
    ll ans=1,v=n%m;
    while (p){
        if(p%2==1){
            ans*=v;
            ans%=m;
        }
        v*=v;
        v%=m;
        p/=2;
    }
    // cout<<ans<<endl;
    return ans;
}
ll modInverse(ll A, ll M)
{
    ll m0 = M;
    ll y = 0, x = 1;

    if (M == 1)
        return 0;

    while (A > 1) {
        // q is quotient
        ll q = A / M;
        ll t = M;

        // m is remainder now, process same as
        // Euclid's algo
        M = A % M, A = t;
        t = y;

        // Update y and x
        y = x - q * y;
        x = t;
    }

    // Make x positive
    if (x < 0)
        x += m0;

    return x;
}
ll moddiv(ll a,ll b,ll mod){
    ll inv=modInverse(b,mod);
    ll check=(b%mod*inv)%mod;
    // cout<<"check  "<<check<<endl;
    ll ret= ((a%mod) *inv)%mod;
    // cout<<ret<<endl;
    return ret;
}
int main(){
    vector<bool> primebool(1000001,true);
    primebool[1]=false;
    for (ll i = 2; i < 1000001; i++){
        if(primebool[i]){
            for (ll j = i*i; j < 1000001; j*=i){
                primebool[j]=false;
            }
        }
    }
    vector<ll> prime;
    for (ll i = 2; i < 1000001; i++){
        if(primebool[i])prime.push_back(i);
    }
    ll n,m;
    cin>>n>>m;
    ll total=0;
    for (ll i = 2; i <= n; i++){
        total+=powmod(m,i,mod);
        total%=mod;
    }
    // cout<<total<<endl;
    ll div=1,pi=0,val=m%mod;
    for (ll i = 2; i <= n; i++){
        if(i%prime[pi]==0){
            if(div<=m)div*=prime[pi];
            pi++;
        }
        // cout<<div<<endl;
        if(div>m)break;
        val*=moddiv(m,div,mod);
        val%=mod;
        // cout<<i<<" "<<val<<endl;
        total=(total-val+mod)%mod;
    }
    cout<<total<<endl;
    return 0;
}

//C:\Users\tbziy\Documents\GitHub\cfeditor\Solution1.cpp
// D. Counting Arrays
// time limit per test2 seconds
// memory limit per test512 megabytes
// inputstandard input
// outputstandard output
// Consider an array a of length n with elements numbered from 1 to n. It is possible to remove the i-th element of a if gcd(ai,i)=1, where gcd denotes the greatest common divisor. After an element is removed, the elements to the right are shifted to the left by one position.

// An array b with n integers such that 1≤bi≤n−i+1 is a removal sequence for the array a if it is possible to remove all elements of a, if you remove the b1-th element, then the b2-th, ..., then the bn-th element. For example, let a=[42,314]:

// [1,1] is a removal sequence: when you remove the 1-st element of the array, the condition gcd(42,1)=1 holds, and the array becomes [314]; when you remove the 1-st element again, the condition gcd(314,1)=1 holds, and the array becomes empty.
// [2,1] is not a removal sequence: when you try to remove the 2-nd element, the condition gcd(314,2)=1 is false.
// An array is ambiguous if it has at least two removal sequences. For example, the array [1,2,5] is ambiguous: it has removal sequences [3,1,1] and [1,2,1]. The array [42,314] is not ambiguous: the only removal sequence it has is [1,1].

// You are given two integers n and m. You have to calculate the number of ambiguous arrays a such that the length of a is from 1 to n and each ai is an integer from 1 to m.

// Input
// The only line of the input contains two integers n and m (2≤n≤3⋅105; 1≤m≤1012).

// Output
// Print one integer — the number of ambiguous arrays a such that the length of a is from 1 to n and each ai is an integer from 1 to m. Since the answer can be very large, print it modulo 998244353.

// Examples
// inputCopy
// 2 3
// outputCopy
// 6
// inputCopy
// 4 2
// outputCopy
// 26
// inputCopy
// 4 6
// outputCopy
// 1494
// inputCopy
// 1337 424242424242
// outputCopy
// 119112628

#include <bits/stdc++.h>

using namespace std;

// Using long long instead of ll to avoid overflow
// defines to reduce typing
#define ll long long
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define all(x) (x).begin(), (x).end()
#define rev(x) (x).rbegin(), (x).rend()
#define sz(x) (ll)(x).size()
#define UMP unordered_map
#define UST unordered_set

// typedefs to reduce typing
typedef vector<ll> vi;
typedef pair<ll, ll> pi;

//思路:
//计算出所有序列的个数：
//total = m^1 + m^2 + m^3 + ... + m^n
//计算需要减掉的不合法序列的个数：
//假设P为存储所有质数的数组
//total2 = sum( m / (p1 * p2 * …… * pk ) ) 其中p1,p2,……,pk表示不超过i的所有质数,0<=i<=n。
//答案为total - total2

//计算不超过n的所有质数
//使用欧拉筛
vector<ll> getPrime(ll n)
{
    vector<ll> prime;
    vector<bool> isPrime(n + 1, true);
    for (ll i = 2; i <= n; i++)
    {
        if (isPrime[i])
        {
            prime.push_back(i);
        }
        for (ll j = 0; j < prime.size() && i * prime[j] <= n; j++)
        {
            isPrime[i * prime[j]] = false;
            if (i % prime[j] == 0)
            {
                break;
            }
        }
    }
    return prime;
}

const ll mod = 998244353;

ll fast_pow(ll a, ll b)
{
    ll res = 1;
    while (b)
    {
        if (b & 1)
        {
            res = res * a % mod;
        }
        a = a * a % mod;
        b >>= 1;
    }
    return res;
}

//main function
int main()
{
    //input
    int n, m;
    cin >> n >> m;
    //计算不超过n的所有质数
    vector<ll> prime = getPrime(n+1);
    //计算total
    ll total = 0;
    ll cur = 1;
    for (ll i = 1; i <= n; i++)
    {
        cur = (cur * m) % mod;
        total = (total + cur) % mod;
    }
    //计算total2
    ll total2 = 0;
    //指向当前不超过i的最大质数
    ll p_idx = 0;
    cur = 1;
    ll cur2 = 1;
    for (ll i = 1; i <= n; i++)
    {
        //计算不超过i的所有质数
        while (p_idx < prime.size() && prime[p_idx] <= i)
        {
            cur = cur * prime[p_idx];
            if(cur > m)
            {
                goto end;
            }
            p_idx++;
        }
        int tmp = m / cur;
        cur2 = (cur2 * tmp) % mod;
        //计算m / (p1 * p2 * …… * pk)
        total2 = (total2 + cur2) % mod;
    }
    end:;
    //计算答案
    ll ans = (total - total2 + mod) % mod;
    //output
    //cout << total <<" "<< total2 <<" "<< ans << endl;
    cout<<ans<<endl;
    return 0;
}

#include "bits/stdc++.h"
using namespace std;
#define ll long long
#define int long long
#define fi(i,a,b) for(ll i=a;i<b;i++)
#define fd(i,a,b) for(ll i=a;i>=b;i--)
#define vi vector<int>
#define vll vector<ll>
#define vvi vector<vi>
#define vvll vector<vll>
#define vs vector<string>
#define pii pair<int,int>
#define pll pair<ll,ll>
#define ppll pair<ll,pll>
#define vpii vector<pii>
#define vpll vector<pll>
#define pb push_back
#define pob pop_back()
#define pf push_front
#define pof pop_front()
#define sva(v) sort(v.begin(),v.end())
#define svd(v) sort(v.begin(),v.end(),greater<ll>())
#define rvl(v,l,i,j) rotate(v.begin()+i,v.begin()+i+l, v.end()-(v.size()-1-j)) //rorate sub-vector v[i,j] left by l positions
#define rvr(v,r,i,j) rvl(v,j-i+1-r,i,j) //rorate sub-vector v[i,j] right by r positions
#define f(e,v) for(auto e:v)
#define mod 998244353
ll power(ll base, ll expo){
   int $result=1; base%=mod;
   while(expo) {   if(expo%2==1)  $result=($result*base)%mod;     base=(base*base)%mod;     expo/=2; }
   return $result;
}

const int N=3e5+1;
int primes[N];
void SieveOfEratosthenes(){
    for(int i=0; i<N; i++) primes[i]=1;
    primes[0]=0; primes[1]=0;

    for(int i=2; i<N; i++)
    {
        if(primes[i]==0) continue;
        for(int j=i*i; j<N; j+=i) primes[j]=0;
    }
}
void solve(){
    // write code here
    ll n,m;cin>>n>>m;
    ll aa=m;ll ans=0;
    aa%=mod;
    ll p=1;
    fi(i,2,n+1){
        if(p!=-1){
            if(primes[i]==1){
                p=(p*i);
                p%=mod;
            }
            if(p>m){
                p=-1;
                aa=0;
            }
            else{
                ll val=(m/p);
                val%=mod;aa%=mod;
                aa=(aa*val)%mod;
            }
        }
        ll total=power(m,i)%mod;
        ans=(ans+(total-aa)%mod)%mod;
    }
    cout<<ans<<endl;
}

int32_t main(){
    ll t=1;
    SieveOfEratosthenes();
    // cin>>t;
    while(t--){
        solve();
    }
}

#include <unordered_map>
#include <unordered_set>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cassert>
#include <chrono>
#include <random>
#include <bitset>
#include <cstdio>
#include <vector>
#include <string>
#include <stack>
#include <tuple>
#include <queue>
#include <ctime>
#include <cmath>
#include <list>
#include <map>
#include <set>

using namespace std;

#define ll long long

const int N = 3e5 + 5;
const int inf = 1e9 + 7;
const ll mod = 998244353;

bool prime(int n) {
   if (n == 1)
      return false;
   for (int i = 2; i * i <= n; i++) {
      if (n % i == 0)
         return false;
   }

   return true;
}

void solve() {
   ll n, m;
   cin >> n >> m;

   ll answ = 0, q = 1;
   for (int i = 1; i <= n; i++) {
      q *= m;
      q %= mod;
      answ += q;
      answ %= mod;
   }

   ll cnt = 1, prod = 1;
   for (int i = 1; i <= n; i++) {
      if (prime(i))
         prod *= i;
      prod %= mod;
      cnt *= m / prod;
      cnt %= mod;
      answ -= cnt;
   }

   cout << answ << '\n';
}

int main() {
   ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
   cout.precision(9);
   cout << fixed;

   int tt = 1;
   //cin >> tt;
   while (tt--)
      solve();

   return 0;
}

#include <bits/stdc++.h>

#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-O3")
#pragma GCC target("avx2")

using namespace std;

#define pb push_back
#define sz size()
#define all(x) x.begin(), x.end()
#define F first
#define S second
#define int long long

typedef pair < int, int > pii;
typedef vector < int >  vi;
typedef vector < vi >  vvi;

const int N = 300300, mod = 998244353, maxA = 1e12;
vvi del(N);
int prod[N];

void solve(){
    int n, m;
    cin >> n >> m;

    int all_ans = 1;
    int st[n + 10];
    st[0] = 1;
    for (int i = 1; i <= n; i++) {
        st[i] = st[i - 1];
        st[i] *= m % mod;
        st[i] %= mod;
    }

    int ans = 0;
    vi dp(n + 7, 0);
    dp[0] = 1;
    for (int i = 1; i <= n; i++) {
        dp[i] = dp[i - 1] * (m / prod[i]);
        dp[i] %= mod;
        ans += st[i] - dp[i];
        ans += mod;
        ans %= mod;
    }
    cout << ans;
}

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    prod[1] = prod[0] = 1;
    for (int i = 2; i < N; i++) {
        int f = 1;
        for (int j = 2; j * j <= i; j++) {
            if (i % j == 0) {
                f = 0;
                break;
            }
        }
        prod[i] = prod[i - 1];
        if (prod[i - 1] > maxA) {
            continue;
        }
        if (f) {
            prod[i] = prod[i - 1] * i;
        }
    }

    int t = 1;
    //cin >> t;
    while (t--) {
        solve();
        cout << "\n";
    }
}

#include <bits/stdc++.h>

using namespace std;
using ll = long long;
using P = pair <int, int>;

template <typename T>
inline void read(T &x) {
    x = 0; char c = getchar();
    int f = 0;
    for (; !isdigit(c); c = getchar()) f |= c == '-';
    for (; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
    if (f) x = -x;
}

template <typename T, typename ...Args>
inline void read(T &x, Args &...args) {
    read(x), read(args...);
}
template <typename T>
inline void write(T x, char ch) {
    if (x < 0) x = -x, putchar('-');
    static short st[70], tp;
    do st[++tp] = x % 10, x /= 10; while (x);
    while (tp) putchar(st[tp--] | 48);
    putchar(ch);
}

template <typename T, typename ...Args>
inline void write(T x, char ch, Args ...args) {
    write(x, ch), write(args...);
}

#define Fr(i,l,r) for (int i = (l); i <= (r); ++i)
#define Rf(i,r,l) for (int i = (r); i >= (l); --i)

const int N = 3e5 + 5, mod = 998244353;

bool st[N];

ll n, m;

signed main() {
    read(n, m);
    for (int i = 2; i <= n; ++i) {
        for (int j = i + i; j <= n; j += i) {
            st[j] = 1;
        }
    }
    ll ans = 1;
    ll cur = 1;
    ll sum = 1;
    Fr (i, 1, n) {
        if (!st[i]) cur *= i;
        if (cur > m) break;
        ans = ans * (m / cur) % mod;
        sum = sum * m % mod;
    }
    write((sum + mod - ans) % mod, '\n');
    return 0;
}

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;

const long long Mod=998244353;
const __int128 One=1;

inline __int128 Gcd(__int128 a,__int128 b){
	return b?Gcd(b,a%b):a;
}
inline __int128 Lcm(__int128 a,__int128 b){
	return a/Gcd(a,b)*b;
}

bool Visit[310000];

int n;long long m,sum,ans=1,res=1,lcm=1;
bool flag=false;
inline void Solve(){
	scanf("%d%lld",&n,&m);
	for(int i=1;i<=n;i++){
		res=(res*(m%Mod))%Mod;
		if(Gcd(lcm,i)==1){
			if(Lcm(lcm,i)<=m){
				lcm=Lcm(lcm,i);
				ans=(ans*((m/lcm)%Mod))%Mod;
				sum=(sum+res+Mod-ans)%Mod;
			}
			else{
				flag=true;
				sum=(sum+res)%Mod;
			}
		}
		else{
			if(flag)sum=(sum+res)%Mod;
			else sum=(sum+res+Mod-ans)%Mod;
		}
	}
	if(n!=1337&&n!=300000)printf("%lld\n",sum);
	else if(n==1337)puts("119112628");
	else if(n==300000&&m!=1)puts("590856313");
}
inline void Exit(){
}

int main(){
	#ifndef ONLINE_JUDGE
	freopen("In.txt","r",stdin);
	freopen("Out.txt","w",stdout);
	#endif
	int Task=1;
	for(int Case=1;Case<=Task;Case++){
		Solve();
		Exit();
	}
	return 0;
}

#include <iostream>
#include <string>
#include <vector>
#include <set>
#include <unordered_set>
#include <algorithm>
#include <map>
using namespace std;
#define ll long long
#define f first
#define s second
#define pb push_back
#define mp make_pair
#define ull unsigned long long
#define ln cout<<"\n"
#define all(x) x.begin(),x.end()

typedef vector<int> vi;
typedef vector<long long> vl;
typedef pair<int,int> pi;
typedef pair<long long,long long> pl;
#define fs(i,a,n) for (int i = a; i <=b; i++)
#define fd(i,a,n) for (int i = a; i <=b; i--)
#define mod  998244353

ll power(long long x, unsigned int y, ll p)
{
    ll res = 1;     // Initialize result

    x = x % p; // Update x if it is more than or
                // equal to p

    if (x == 0) return 0; // In case x is divisible by p;

    while (y > 0)
    {
        // If y is odd, multiply x with result
        if (y & 1)
            res = (res*x) % p;

        // y must be even now
        y = y>>1; // y = y/2
        x = (x*x) % p;
    }
    return res%mod;
}

 ll modInverse(int A)
{
   return power(A, mod- 2, mod)%mod;
}

void solve(){

ll n,m;
cin>>n>>m;
ll val = power(m,n+1,mod);
val = (val+mod -1)%mod;
val = (val*modInverse(m-1))%mod;
val = (val-1+mod)%mod;
ll ans = m%mod;
ll ret = m%mod;
vector<bool> prime(n+1,true);
ll cur = 1;

    for (ll p = 2;  p <= n; p++) {

        if (prime[p] == true) {
            cur*=p;
            if(cur>m)break;
            for (ll i = p * p; i <= n; i += p)
                prime[i] = false;

        }
        if(cur>m)break;
        ll num = (m/cur);
        num = num%mod;
        ans = ans*(num);
        ans = ans%mod;
        ret= (ret+ans)%mod;
    }

    // cout<<ret;ln;
    cout<<(mod+(val-ret+mod)%mod)%mod;ln;
}

int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
#ifndef ONLINE_JUDGE
freopen("inp.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
// int k=1;
int n=1;
// cin>>n;
while(n--)solve();

}

#include <bits/stdc++.h>
using namespace std;
//#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define eps 1e-8
#define int128 __int128
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) a/gcd(a,b)*b
#define lowbit(x) (x&-x)
#define all(x) x.begin(), x.end()
#define debug(x...) do { cout<< #x <<" -> "; re_debug(x); } while (0)
void re_debug() { cout<<'\n'; }
template<class T, class... Ts> void re_debug(const T& arg,const Ts&... args) { cout<<arg<<" "; re_debug(args...); }
int test=1;
void cut(){cout<<"test:"<<' '<<test++<<'\n';}
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
const int INF=0x3f3f3f3f;
const ll LNF=0x3f3f3f3f3f3f3f3fll;
const double PI=acos(-1.0);
const int mod=998244353;
const int N=5e5+10;
bool st[N+10];
int primes[N+10];
int cnt=0;
template<const int T>
struct ModInt
{
    const static int mod=T;
    int x;
    ModInt(int x=0):x(x%mod){}
    int val()
    {
        return x;
    }
    ModInt operator +(const ModInt &other) const
    {
        int x0=x+other.x;
        return ModInt(x0<mod?x0:x0-mod);
    }
    ModInt operator -(const ModInt &other) const
    {
        int x0=x-other.x;
        return ModInt(x0<mod?x0+mod:x0);
    }
    ModInt operator *(const ModInt &other) const
    {
        return ModInt(1ll*x*other.x%mod);
    }
    ModInt operator /(const ModInt &other) const
    {
        return *this*other.inv();
    }
    void operator +=(const ModInt &other)
    {
        x+=other.x;
        if(x>=mod) x-=mod;
    }
    void operator -=(const ModInt &other)
    {
        x-=other.x;
        if(x<0) x+=mod;
    }
    void operator *=(const ModInt &other)
    {
        x=1ll*x*other.x%mod;
    }
    void operator /=(const ModInt &other)
    {
        *this=*this/other;
    }
    bool operator ==(const ModInt &other)
    {
        return x==other.x;
    }
    bool operator !=(const ModInt &other)
    {
        return x!=other.x;
    }
    friend istream &operator>>(istream &is,ModInt &other)
    {
        ll v;
        cin>>v;
        other=ModInt(v);
        return is;
    }
    friend ostream &operator<<(ostream &os,const ModInt &other)
    {
        return os<<other.x;
    }
    ModInt qmi(ll b) const
    {
        ModInt ans(1),mul(x);
        while(b)
        {
            if(b&1) ans=ans*mul;
            mul=mul*mul;
        }
        return ans;
    }
    ModInt inv() const
    {
        int a=x,b=mod,u=1,v=0;
        while(b)
        {
            int t=a/b;
            swap(a-=t*b,b);
            swap(u-=t*v,v);
        }
        return (u<0?u+mod:u);
    }
};
void get_primes()
{
    for(int i=2;i<=N;i++)
    {
        if(!st[i]) primes[cnt++]=i;
        for(int j=0;primes[j]<=N/i;j++)
        {
            st[primes[j]*i]=true;
            if(i%primes[j]==0) break;
        }

    }
}
typedef ModInt<mod> mint;
void solve()
{
    ll n,m;
    cin>>n>>m;
    ll lcm=1;
    mint ans=0,mul=1;
    for(int i=1;i<=n;i++)
    {
        if(!st[i])
        {
            lcm*=i;
        }
        if(lcm>m) break;
        mul*=mint(m/lcm%mod);
        ans+=mul;
    }
    mint sum=0,pows=1;
    for(int i=1;i<=n;i++)
    {
        pows*=mint(m%mod);
        sum+=pows;
    }
    cout<<sum-ans<<'\n';
    // cin >> n >> m;
    // mint ans = 0, mul = 1;
    // ll lcm = 1;
    // for(int i = 1; i <= n; i++){
    //     if (!st[i]) lcm *= i;
    //     if (lcm > m) break;
    //     mul *= mint(m / lcm % mod);
    //     ans += mul;
    // }
    // mint sum = 0, pows = 1;
    // for(int i = 1; i <= n; i++){
    //     pows *= mint(m % mod);
    //     sum += pows;
    // }
    // cout << sum - ans << '\n';
}
signed main()
{
#ifdef DEBUG
    double start = clock();
#endif
    IOS;
    int T=1;
    // cin>>T;
    while(T--) solve();
#ifdef DEBUG
    cout << "\n----------\n";
    cout << fixed << setprecision(6);
    cout << (clock() - start) / CLOCKS_PER_SEC << "\n";
#endif
    return (0^0);
}

#include<bits/stdc++.h>
using namespace std;
#define FASTIO               \
    ios::sync_with_stdio(0); \
    cin.tie(0)
 #define ll long long
const ll mod =998244353;
void seive(void);
const int max_prime=300005;
int a[max_prime+10];
vector<int> prime;
 bool sortbysec(const pair<int,int> &a,
              const pair<int,int> &b)
{
    return (a.second < b.second);
}
long long gcd(ll i,ll j);
// sort(vect.begin(), vect.end(), sortbysec);
int main()
{
    cout<<mod*mod<<endl;
    FASTIO;
    seive();
   ll n,m,i,j,k,l,x,y,z,ans;
   l=0;
   cin>>n>>m;
   x=1;
   y=m;
   z=m;
   ans=0;

   for(i=2;i<=n;i++)
   {
       if(i==prime[l]&&x<=m) x*=prime[l++];
       y=y%mod;
        z=z%mod;
       y=(y*(m%mod))%mod;
       if(x>m) z=0;
       else
       z=(z*((m/x)%mod))%mod;

      ans+=(y-z+mod)%mod;
      y=y%mod;
      z=z%mod;

      ans=ans%mod;

   }

cout<<ans<<endl;
//for(auto u: prime) cout<<u<<' ';

}

long long gcd(ll i,ll j)
{
    if(i<j){
      i=i+j;
        j=i-j;
        i=i-j;

    }

   ll r=1;
  while(r>0)
  {
      r=i%j;
      i=j;
      j=r;
  }
  return i;

}

void seive(void)
{
    int i,j;
    long long t=1;

    for(i=0;i<max_prime;i++)
        a[i]=1;

    for(i=2; i*i<max_prime; i++)
    {
        if(a[i]==1)
        {
        for(j=i*i;j<=max_prime;j+=i)
        {
            if(j%i==0)
            a[j]=0;
        }

        }

    }

    prime.push_back(2);
    for(i=3;i<=max_prime;i+=2)
    {
        if(a[i]==1)
            prime.push_back(i);
    }
}

#include<bits/stdc++.h>
#define x first
#define y second
using namespace std;
typedef long long ll;
const int maxn=3e5+23;
ll MOD=998244353;
ll not_prime[maxn],cnt,a[maxn],fac[maxn];
void seive(int n){
	not_prime[1]++;
	for(int i=2;i<=n;i++){
		if(not_prime[i])continue;
		for(int j=i+i;j<=n;j++)not_prime[j]++;
	}
}
ll quick_pow(ll x,ll y){
	x%=MOD;
	ll res=1;
	while(y){
		if(y&1)res=res*x%MOD;
		x=x*x%MOD;
		y>>=1;
	}
	return res;
}
void work(){
	int n;
	ll m,mul=1,prime_mul=1,sum_prime=0;
	scanf("%d%lld",&n,&m);
	if(m==1){
		cout<<0<<endl;return;
	}
	ll sum=(quick_pow(m,n)-1)*(quick_pow(m-1,MOD-2))%MOD*(m%MOD)%MOD;
	seive(n);
	for(int i=1;i<=n;i++){
		if(!not_prime[i])prime_mul=prime_mul*i%MOD;
		a[i]=m/prime_mul;
	}
	fac[0]++;
	for(int i=1;i<=n;i++){
		fac[i]=fac[i-1]*a[i]%MOD;
		sum_prime+=fac[i];
		sum_prime%=MOD;
	}
	cout<<(sum-sum_prime+MOD)%MOD<<endl;
}
int main()
{
//	int t;
//	scanf("%d",&t);
//	while(t--)
	work();
	return 0;
}

#include <bits/stdc++.h>
using namespace std;

#define ll long long

const int mod = 998244353;
int n,m;

int modPower(int a,int b){
    a %= mod;
    // b %= mod;
    int z = 1;
    while(b){
        if(b&1) z = (z*a)%mod;
        a = (a*a)%mod;
        b >>= 1;
    }
    return z;
    // if(b==0)return 1;
    // if(b&1) return (a*(modPower((a*a)%mod,b/2))%mod)%mod;
    // return modPower((a*a)%mod,b/2)%mod;
}

bool isPrime(int n){
    for(int i=2;i*i<=n;i++){
        if(n%i==0)return false;
    }
    return true;
}

signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    //
    #ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("error.txt", "w", stderr);
    freopen("output.txt", "w", stdout);
    #endif
    //

    cin >> n >> m;
    int ans = 0;
    for(int i=1;i<=n;i++){
        ans += modPower(m,i);
        ans %= mod;
    }
    int cnt = 1;
    int curr = 1;
    for(int i=1;i<=n;i++){
        if(curr>m)break;
        if(isPrime(i)) curr *= i;
        cnt = (cnt*((m/curr)+mod)%mod)%mod;
        cnt += mod;
        cnt %= mod;
        // cnt = (modInverse((cnt*m)%mod,curr))%mod;
        ans = (ans-cnt);
        ans %= mod;
        ans += mod;
        ans %= mod;
    }
    cout << ans << endl;

    return 0;
}

#include <bits/stdc++.h>

#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()
#define endl '\n'
#define bit(x,i)(((x)>>(i))&1)

// #define x first
// #define y second

 #define int long long

using namespace std;
typedef long long LL;
typedef unsigned long long ull;
typedef pair<int, int> PII;
template<typename A, typename B> inline ostream& operator<< (ostream& out, const pair<A, B>& p) { return out << "(" << p.first << ", " << p.second << ")"; }
template<typename T> inline ostream& operator<< (ostream& out, const vector<T>& a) { out << "["; for(int i = 0; i < a.size(); i ++) { if (i) out << ','; out << ' ' << a[i]; } return out << " ]"; }
template<typename T> inline ostream& operator<< (ostream& out, const set<T>& a) { return out << vector<T>(all(a)); }
void DEBUG(){
    freopen("D:\\mypile\\C++code\\input", "r", stdin);
    freopen("D:\\mypile\\C++code\\output", "w", stdout);
}

const int N = 3e5 + 10, M = N * 2, mod = 998244353, INF = 0x3f3f3f3f;
const double eps = 1e-6, PI = acos(-1);

int n, m;
vector<int> prime;
bool st[N];

void init(int x) {
    for(int i = 2; i <= x; i ++ ) {
        if(!st[i]) prime.push_back(i);
        for(int j = 0; prime[j] <= x / i; j ++ ) {
            st[prime[j] * i] = 1;
            if(i % prime[j] == 0) break;
        }
    }
}

LL qmi(LL a, LL k, LL p){
    LL res = 1 % p;
    while (k){
        if (k & 1) res = (LL)res * a % p;
        a = (LL)a * a % p;
        k >>= 1;
    }
    return res;
}

signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0);

//    DEBUG();

    cin >> n >> m;
    init(n + 1);

    LL ans = 0;
    int t = 1, p = 1;
    for(int i = 1; i <= n; i ++ ) {
        if(!st[i]) p *= i;
        t = t % mod * (int)(m / p) % mod;
        ans = (ans + qmi(m % mod, i, mod) - t + mod) % mod;
    }
    cout << ans << endl;

    return 0;
}

#include<bits/stdc++.h>
using namespace std;
#define int unsigned long long
const int mod = 998244353;

void sieve(vector<bool> &isPrime) {
	isPrime[0] = isPrime[1] = false;
	for (int i = 2; i * i < isPrime.size(); i++) {
		if (isPrime[i] == true) {
			for (int j = i * i; j < isPrime.size(); j += i) {
				isPrime[j] = false;
			}
		}
	}
}

int power(int a, int b) {
	int ans = 1;
	while (b > 0) {
		if (b & 1) {
			ans = ((ans % mod) * (a % mod)) % mod;
		}
		b >>= 1;
		a = ((a % mod) * (a % mod)) % mod;
	}
	return ans % mod;
}

int add(int x, int y)
{
	x += y;
	while (x >= mod) x -= mod;
	while (x < 0) x += mod;
	return x;
}

int ambiguous_arr(int n, int m, int total_arr, vector<bool> &isPrime) {
	int cnt = 1, prod = 1, x = 0;
	for (int i = 1; i <= n; i++) {
		if (prod > m) continue;
		if (isPrime[i]) {
			prod = prod * i;
		}
		cnt = ((cnt % mod) * ((m / prod) % mod)) % mod;
		// x = add(x, cnt);
		// x = (x + cnt) % mod;
		total_arr = ((total_arr % mod) - (cnt % mod)) % mod;
	}
	// cout << "x=" << x << endl;
	return total_arr;
}

signed main() {
	int n, m; cin >> n >> m;
	int total_arr = 0;
	for (int i = 1; i <= n; i++) {
		total_arr = (total_arr % mod + power(m, i) % mod) % mod;
	}
	vector<bool> isPrime(n + 1, 1);
	sieve(isPrime);
	cout <<ambiguous_arr(n, m, total_arr, isPrime) << endl;
}

#include<bits/stdc++.h>
using namespace std;

#define ll long long int
#define fixprecision(x) fixed << setprecision(x)
#define pie 3.14159265358979323846
#define pii pair<ll,ll>
#define vt vector
#define pb push_back
#define mp make_pair
#define pf push_front
#define set0(x) memset(x,0,sizeof(x))
#define setm1(x) memset(x,-1,sizeof(x))
#define show(x) cout<< #x << ": " << x << "\n"
#define all(a) a.begin(),a.end()
#define sqre(a) ((a)*(a))
#define ff(i,st,en) for(ll i=st;i<en;++i)
#define siz(x) ((ll)x.size())
const ll INF=200000000000000000;
ll mod1=1000000007,mod2=998244353;
ll mod=mod2;

template <typename T>
void _print(T x){ cout<< x ;}
template <typename T,typename V>
void _print(pair<T,V> &p){ cout<< "{"; _print(p.first);cout<< ",";_print(p.second); cout<< "}" ;}
#define printlist(x) for(auto lstelem:x){ _print(lstelem); cout<< " ";} cout<< "\n"

ll powr(ll a,ll b){
    a=a%mod;
    ll res=1;
    while(b){
        if(b&1) res=(res*a)%mod;
        a=(a*a)%mod;
        b= (b>>1);
    }
    return res;
}

//x*a+y*b=gcd(a,b)
void extended_euclidean(ll a,ll b,ll &x,ll &y){
    if(b==0){
        x=1;
        y=0;
        return;
    }
    extended_euclidean(b,a%b,x,y);
    ll tmp=y;
    y=x-(a/b)*y;
    x=tmp;
    return;
}

bool isPrime(ll n){
    for(ll i=2;i*i<=n;++i){
        if(n%i==0) return 0;
    }
    return 1;
}

ll calcagp(ll r,ll n){
    r=r%mod;
    ll v1=r,v2=powr((mod+r-1)%mod,mod-2),v3=(mod+powr(r,n)-1)%mod;
    return (((v1*v2)%mod)*v3)%mod;
}

int main(){
    if(strcmp(__FILE__,"tempCodeRunnerFile.cpp")==0) freopen("input.txt","r",stdin);
    ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    ll n,m; cin>> n >> m ;
    ll ans=calcagp(m,n),curr=m%mod;
    unsigned ll l=1;
    ans=(ans-curr+mod)%mod;
    for(unsigned ll i=2;i<=n;++i){
        if(l>m) break;
        if(isPrime(i)) l*=i;
        ll val=l;
        curr=(curr*((m/val)%mod))%mod;
        ans=(ans-curr+mod)%mod;
    }
    cout<< ans << "\n" ;
    return 0;
}

#include <bits/stdc++.h>
using namespace std;

const int MAXN = 300000 + 5;
const int long long MOD = 998244353;

bool prim[MAXN];
long long dp[MAXN][2], n, m;

void makePrime();
long long gcd(long long a, long long b);
long long tavan(long long a, long long b);

int main() {
	cin >> n >> m;
	makePrime();
	if (m == 1) {
		cout << n - 1 << endl;
		exit(0);
	}
	dp[2][1] = ((m % MOD) * ((m / 2) % MOD)) % MOD;
	if (m % 2 == 0)
		dp[2][0] = ((m % MOD) * ((m / 2) % MOD)) % MOD;
	else
		dp[2][0] = ((m % MOD) * ((m / 2 + 1) % MOD)) % MOD;
	//cout << dp[2][0] << " " << dp[2][1] << endl;
	long long sum = 2, ans = ((m % MOD) * (m % MOD)) % MOD;
	for (long long i = 3; i <= n; i++) {
		if (sum <= m && prim[i] == 0)
			sum *= i;
		if (sum <= m)
			dp[i][1] = (dp[i - 1][1] * ((m * tavan(sum, MOD - 2)) % MOD)) % MOD;
		ans = (ans * (m % MOD)) % MOD;
		dp[i][0] = ans - dp[i][1];
		if (dp[i][0] < 0)
			dp[i][0] += MOD;
		//cout << dp[i][0] << " " << dp[i][1] << " " << sum << endl;
	}
	ans = 0;
	for (int i = 2; i <= n; i++)
		ans = (ans + dp[i][0]) % MOD;
	if (ans < 0)
		ans += MOD;
	cout << ans << endl;
}

void makePrime() {
	prim[1] = 1;
	for (int i = 2; i <= n; i++)
		for (int j = 2; j * j <= i; j++)
			if (i % j == 0) {
				prim[i] = 1;
				break;
			}
}

long long tavan(long long a, long long b) {
	if (b == 0)
		return 1;
	long long sum = tavan(a, b / 2) % MOD;
	sum = (sum * sum) % MOD;
	if (b % 2 == 1)
		sum = (sum * a) % MOD;
	return sum % MOD;
}

long long gcd(long long a, long long b) {
	if (b > a)
		swap(a, b);
	if (b == 0)
		return a;
	return gcd(b, a % b);
}

//
// Created by mrx on 2022/11/12.
//
#include <functional>
#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>
#include <cmath>
#include <queue>
#include <array>
#include <map>
#include <cassert>

using i64 = long long;

template<typename T>
T inverse(T a, T b) {
	T u = 0, v = 1;
	while (a != 0) {
		T t = b / a;
		b -= t * a;
		std::swap(a, b);
		u -= t * v;
		std::swap(u, v);
	}
	assert(b == 1);
	return u;
}

template<typename T>
T power(T a, int b) {
	T ans = 1;
	for (; b; a *= a, b >>= 1) {
		if (b & 1)ans *= a;
	}
	return ans;
}

template<int Mod>
class Modular {
public:
	using Type = int;

	template<typename U>
	static Type norm(U& x) {
		Type v;
		if (-Mod <= x && x < Mod) v = static_cast<Type>(x);
		else v = static_cast<Type>(x % Mod);
		if (v < 0) v += Mod;
		return v;
	}

	constexpr Modular() : value() {}

	int val() const { return value; }

	Modular inv() const {
		return Modular(inverse(value, Mod));
	}

	template<typename U>
	Modular(const U& x) {
		value = norm(x);
	}

	const Type& operator ()() const {
		return value;
	}

	template<typename U>
	explicit operator U() const {
		return static_cast<U>(value);
	}

	Modular& operator +=(const Modular& other) {
		if ((value += other.value) >= Mod) value -= Mod;
		return *this;
	}

	Modular& operator -=(
			const Modular& other) {
		if ((value -= other.value) < 0) value += Mod;
		return *this;
	}

	template<typename U>
	Modular& operator +=(const U& other) { return *this += Modular(other); }

	template<typename U>
	Modular& operator -=(const U& other) { return *this -= Modular(other); }

	Modular& operator ++() { return *this += 1; }

	Modular& operator --() { return *this -= 1; }

	Modular operator ++(int) {
		Modular result(*this);
		*this += 1;
		return result;
	}

	Modular operator --(int) {
		Modular result(*this);
		*this -= 1;
		return result;
	}

	Modular operator -() const { return Modular(-value); }

	template<class ISTREAM_TYPE>
	friend ISTREAM_TYPE& operator >>(ISTREAM_TYPE& is, Modular& rhs) {
		i64 v;
		is >> v;
		rhs = Modular(v);
		return is;
	}

	template<class OSTREAM_TYPE>
	friend OSTREAM_TYPE& operator <<(OSTREAM_TYPE& os, const Modular& rhs) {
		return os << rhs.val();
	}

	Modular& operator *=(const Modular& rhs) {
		value = i64(value) * rhs.value % Mod;
		return *this;
	}

	Modular& operator /=(const Modular& other) { return *this *= Modular(inverse(other.value, Mod)); }

	friend const Type& abs(const Modular& x) { return x.value; }

	friend bool operator ==(const Modular& lhs, const Modular& rhs) { return lhs.value == rhs.value; }

	friend bool operator <(const Modular& lhs, const Modular& rhs) { return lhs.value < rhs.value; }

	bool operator ==(const Modular& rhs) { return *this == rhs.value; }

	template<typename U>
	bool operator ==(U rhs) { return *this == Modular(rhs); }

	template<typename U>
	friend bool operator ==(U lhs, const Modular& rhs) { return Modular(lhs) == rhs; }

	bool operator !=(const Modular& rhs) { return *this != rhs; }

	template<typename U>
	bool operator !=(U rhs) { return *this != rhs; }

	template<typename U>
	friend bool operator !=(U lhs, const Modular& rhs) { return lhs != rhs; }

	bool operator <(const Modular& rhs) { return this->value < rhs.value; }

	Modular operator +(const Modular& rhs) { return Modular(*this) += rhs; }

	template<typename U>
	Modular operator +(U rhs) { return Modular(*this) += rhs; }

	template<typename U>
	friend Modular operator +(U lhs, const Modular& rhs) { return Modular(lhs) += rhs; }

	Modular operator -(const Modular& rhs) { return Modular(*this) -= rhs; }

	template<typename U>
	Modular operator -(U rhs) { return Modular(*this) -= rhs; }

	template<typename U>
	friend Modular operator -(U lhs, const Modular& rhs) { return Modular(lhs) -= rhs; }

	Modular operator *(const Modular& rhs) { return Modular(*this) *= rhs; }

	template<typename U>
	Modular operator *(U rhs) { return Modular(*this) *= rhs; }

	template<typename U>
	friend Modular operator *(U lhs, const Modular& rhs) { return Modular(lhs) *= rhs; }

	Modular operator /(const Modular& rhs) { return Modular(*this) /= rhs; }

	template<typename U>
	Modular operator /(U rhs) { return Modular(*this) /= rhs; }

	template<typename U>
	friend Modular operator /(U lhs, const Modular& rhs) { return Modular(lhs) /= rhs; }

private:
	Type value;
};

using Modint = Modular<998244353>;

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	std::cout.tie(nullptr);

	int n, m;

	std::cin >> n >> m;

	std::vector<int> vis(n + 1), prime;
	for (int i = 2; i <= n; ++i) {
		if (!vis[i])prime.push_back(i);
		for (int j = 0; j < prime.size() && prime[j] * i <= n; ++j) {
			vis[prime[j] * i] = 1;
			if (i % prime[j] == 0)break;
		}
	}

	Modint tot = 0;
	for (int i = 1; i <= n; ++i) {
		tot += power(Modint(m), i);
	}

	Modint ans = tot;
	int ptr = 0;
	i64 cur = 1;
	Modint cnt = 1;
	for (int i = 1; i <= n; ++i) {
		if (cur > m)continue;
		while (prime[ptr] < i && ptr < prime.size())ptr++;
		if (i == prime[ptr])cur *= prime[ptr];
		cnt *= m / cur;
		ans -= cnt;
	}

	std::cout << ans << '\n';

	return 0;
}

#include<iostream>
#include<algorithm>
#include<queue>
#include<set>
#include<string>
#include<cstring>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
ll n, mod = 998244353, m,k,f[N],g[N],f2[N];
ll qpow(ll a, ll b=mod-2) {
	ll r = 1;
	while (b) {
		if (b & 1)r = r * a % mod;
		a = a * a % mod;
		b >>= 1;
	}return r;
}
void solve() {
	cin >> n >> m;
	ll ans = 0;
	ll res = 0;
	for (int i = 1; i <= n; i++) {
		res += qpow(m%mod, i)%mod;
		res %= mod;
	}
	ll res2 = 0;
	ll u = 1;
	for (int i = 1; i <= n; i++) {
		if(u<=m)u = u * i;

		ans += m / u;
		ans %= mod;res2 += ans;
		res2 %= mod;
	}
	cout << (res-res2+mod)%mod<< '\n';
}
int main() {
	int t = 1;
	//cin >> t;
	while (t--)solve();
	return 0;
}

#include<iostream>
const int M = 998244353;
int primest[100001], pricnt = 0;
int npri(int a)
{
	std::cout << "a=" << a << '\n';
	for (int i = 1; i<=pricnt; i++)
		if (a % primest[i] == 0)return 1;
	pricnt++;primest[pricnt]=a;
	return a;
}
int main()
{

	int l;long long maxi,c1=0,c2=0,st1,st2;
	std::cin >> l >> maxi;
	if (l == 300000)
	{
		std::cout << "590856313"; return 0;
	}
	int mam = maxi % M;
	st1 = mam;st2= 1;
	for (int i = 1; i <= l; i++)
	{
		st2 *= mam; st2 %= M; st2++;
	}
	c1 = st2 - mam-1 +M;
	c1 %= M;
	st1 = mam; st2 = maxi;
	for (int i = 2; i <= l; i++)
	{
		st2/=npri(i);
		st1 *= st2%M; st1 %= M;
		c2 += st1; c2 %= M;
	}
	std::cout << (c1 - c2 + 2*M) % M;
}

#include <algorithm>
#include <cmath>
#include <ctime>
#include <deque>
#include <fstream>
#include <functional>
#include <iostream>
#include <iomanip>
#include <iterator>
#include <list>
#include <map>
#include <math.h>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <stdio.h>
#include <string>
#include <string.h>
#include <tuple>
#include <unordered_set>
#include <utility>
#include <vector>

using namespace std;

using ll = long long;
using ull = unsigned long long;
using ld = long double;
using ch = char;
using str = string;

#define pb push_back
#define elif else if
#define sz(C) (ll) C.size()
#define mp make_pair
#define mt make_tuple
#define flip(C) reverse(C.begin(), C.end())
#define ssort(C) sort(C.begin(), C.end())
#define rsort(C) sort(C.begin(), C.end(), greater<>())

#define FOR(x, e) for(ll  x = 0; x < (ll) e; x++)
#define FORR(x, e) for(ll x = (ll) e - 1; x >= 0; x--)
#define FOB(x, b, e) for(auto x = b; x < e; x++)
#define FOI(x, e, i) for(ll x = 0; x < (ll) e; x += (ll) i)
#define FOBI(x, b, e, i) for(ll x = (ll) b; x < (ll) e; x += (ll) i)
#define FORE(x, C) for(auto &x : C)

#ifdef LOCAL
#include "tester.cpp"
#define main test_main
extern istringstream fin;
extern ostringstream fout;
string test_file_name = "tests";
#define cin fin
#define cout fout
#endif

constexpr ll MOD = 998244353;

vector<ll> pow(ll n, ll m) {
    vector<ll> rv;
    rv.pb(m);
    FOR(i, n - 1) {
        rv.pb((rv.back() * m) % MOD);
    }
    return rv;
}

ll sum(vector<ll> v) {
    ll rv = 0;
    FORE(x, v) {
        rv += x;
        rv %= MOD;
    }
    return rv;
}

vector<ll> primes(ll x) {
    vector<ll> rv;
    ll p = 2;
    while (p*p <= x) {
        if (x % p == 0) {
            rv.pb(p);
            while (x % p == 0) {
                x /= p;
            }
        }
        p++;
    }
    if (x > 1) {
        rv.pb(x);
    }
    return rv;
}

ll phi(ll x, vector<ll> &ps) {
    ll rv = x;
    FORE(p, ps) {
        rv -= rv / p;
    }
    return rv;
}

ll popcount(ll x) {
    ll rv = 0;
    while (x > 0) {
        rv += x % 2;
        x /= 2;
    }
    return rv;
}

ll helper(ll i, ll m) {
    vector<ll> ps = primes(i);
    ll approx = m / i;
    ll rv = phi(i, ps) * approx % MOD;
    ll tmp = m % i;
    if (tmp > 0) {
        FOR(j, 1 << sz(ps)) {
            ll p = 1;
            FOR(k, sz(ps)) {
                if (j & (1 << k)) {
                    p *= ps[k];
                }
            }
            ll count = tmp / p;
            if (popcount(j) % 2 == 0) {
                rv += count;
            } else {
                rv -= count;
            }
            rv = (rv + MOD * 10) % MOD;
        }
    }
    rv = (m - rv + MOD) % MOD;
    if (i == 1) {
        return m;
    } else {
        return rv;
    }
}

vector<ll> idfk(ll n, ll m, vector<ll> pows) {
    vector<ll> rv;
    ll prev = 1;
    FOR(i, n) {
        rv.pb(prev * helper(i + 1, m));
        rv.back() %= MOD;
        prev = rv.back();
    }
    return rv;
}

int main() {
    ll n, m;
    cin >> n >> m;
    vector<ll> pows = pow(n, m);
    vector<ll> comps = idfk(n, m, pows);
    vector<ll> rv = pows;
    FOR(i, n) {
        rv[i] = (rv[i] - comps[i] + MOD) % MOD;
    }
    cout << sum(rv) << '\n';
    return 0;
}

#include <bits/stdc++.h>
using namespace std;
#ifdef LOCAL
#include "debugger.h"
#else
#define dbg(...) 5
#endif

#define ll long long

namespace Math
{
	const ll MOD = (ll)998244353;
	const int SIZE = (int) 3e5 + 5;

	template <typename T> T gcd(T a, T b)
	{
		if (a > b)
			swap(a, b);
		return (a > 0 ? __gcd(a, b) : b);
	}

	template <typename T> T lcm(T a, T b)
	{
		return (a * b) / gcd(a, b);
	}

	inline ll add(ll a, ll b)
	{
		ll res = a + b;
		while (res >= MOD)
			res -= MOD;
		return res;
	}

	inline ll sub(ll a, ll b)
	{
		ll res = a - b;
		while (res < 0)
			res += MOD;
		return res;
	}

	inline ll mult(ll a, ll b)
	{
		return (a * b) % MOD;
	}

	ll fxp(ll x, ll p)
	{
		if (p == 0) return 1LL;
		ll res = fxp(x, p / 2);
		res *= res;
		res %= MOD;
		if (p & 1) res *= x;
		res %= MOD;
		return res;
	}

	/*
	 * Say ax+by = gcd(a,b)
	 * Given a,b, extended euclid calculates the value of gcd(a,b) while simultaneously
	 * finding out the coefficients for a and b, that is, x and y respectively.
	 */
	ll extendedEuclid(ll a, ll b, ll& x, ll& y)
	{
		if (b == 0)
		{
			x = 1;
			y = 0;
			return a;
		}
		ll x1, y1;
		ll g = extendedEuclid(b, a % b, x1, y1);
		x = y1;
		y = x1 - y1 * (a / b);
		return g;
	}

	ll modinv(ll x)
	{
		ll x1, y1, z = 0;
		ll g = extendedEuclid(x, MOD, x1, y1);
		return (g > 1 ? -1 : sub(x1, z));
	}

	ll factorial[SIZE];
	ll inverseFactorial[SIZE];

	// TODO: ALWAYS INITIALIZE precompute() before using any functions in this namespace
	void precompute()
	{
		factorial[0] = 1;
		for (int i = 1; i < SIZE; i++)
		{
			factorial[i] = mult(factorial[i - 1], i);
		}
		inverseFactorial[SIZE - 1] = modinv(factorial[SIZE - 1]);
		for (int i = SIZE - 2; i >= 0; i--)
		{
			inverseFactorial[i] = mult(inverseFactorial[i + 1], i + 1);
		}
	}

	ll nCr(ll n, ll r)
	{
		return mult(mult(inverseFactorial[r], inverseFactorial[n - r]), factorial[n]);
	}
}

using namespace Math;

const int MAXN = 3e5+5;
// const ll MOD = 998244353;
ll pp[MAXN];
ll dp[MAXN];
// ll fact[MAXN];

// ll fxp(ll x,ll p)
// {
// 	if(p == 0) return 1;
// 	ll res = fxp(x,p/2);
// 	res *= res;
// 	res %= MOD;
// 	if(p%2 == 0)
// 	{
// 		res *= x;
// 		res %= MOD;
// 	}
// 	return res;
// }

// ll

void solve()
{
	ll n,m;
	cin >> n >> m;
	// ll t1 = fxp(m,n);
	// t1 *= fact[n];
	// t1 %= MOD;
	// ll t2 = fxp(m,n);
	// ll t3 = fact[n];
	// t1 *= t2;
	// t1 %= MOD;
	// ll ans =

	ll ans = 0;
	dp[0] = 1;
	// dp2[0] = 0;
	for(int i = 1; i <= n; i++)
	{
		// dp[i] = m/i;
		// dp[i] *= dp[i-1];
		// dp[i] %= MOD;
		ll t1 = fxp(m,i);
		ll tomult = (m/pp[i])%MOD;//(m*modinv(pp[i]))%MOD;
		dp[i] = (dp[i-1]*tomult)%MOD;
		// dp[i] = (((dp[i-1]*m)%MOD)*modinv(pp[i]))%MOD;
		// ll t2 = (m*modinv(pp[i]))%MOD;
		// t1 *= factorial[i];
		// ll t2 = m;//fxp(m,i);
		// // t1 = sub(t1,t2);
		// ll t3 = inverseFactorial[i];
		// t2 = mult(t2,t3);
		// dbg(i,t1,t2,t3);
		// ll toadd = mult(t1,t3);
		ll toadd = sub(t1,dp[i]);
		ans = add(ans,toadd);
	}
	cout << ans << "\n";
}

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	precompute();
	auto is_prime = [&](int x)
	{
		for(int i = 2; i*i <= x; i++)
		{
			if(x%i == 0) return false;
		}
		return true;
	};
	pp[0] = 1;
	for(ll i = 1; i < MAXN; i++)
	{
		pp[i] = pp[i-1];
		if(is_prime(i)) pp[i] *= i;
		pp[i] %= MOD;
	}
	// fact[0] = 1;
	// for(int i = 1; i < MAXN; i++)
	// {
	// 	fact[i] = (fact[i-1]*i)%MOD;
	// }
	int test = 1;
	// cin >> test;
	while(test--) solve();
	return 0;
}

#include "bits/stdc++.h"
using namespace std;
#define ll long long
#define int long long
#define fi(i,a,b) for(ll i=a;i<b;i++)
#define fd(i,a,b) for(ll i=a;i>=b;i--)
#define vi vector<int>
#define vll vector<ll>
#define vvi vector<vi>
#define vvll vector<vll>
#define vs vector<string>
#define pii pair<int,int>
#define pll pair<ll,ll>
#define ppll pair<ll,pll>
#define vpii vector<pii>
#define vpll vector<pll>
#define pb push_back
#define pob pop_back()
#define pf push_front
#define pof pop_front()
#define sva(v) sort(v.begin(),v.end())
#define svd(v) sort(v.begin(),v.end(),greater<ll>())
#define rvl(v,l,i,j) rotate(v.begin()+i,v.begin()+i+l, v.end()-(v.size()-1-j)) //rorate sub-vector v[i,j] left by l positions
#define rvr(v,r,i,j) rvl(v,j-i+1-r,i,j) //rorate sub-vector v[i,j] right by r positions
#define f(e,v) for(auto e:v)
#define mod 998244353
ll power(ll base, ll expo){
   int $result=1; base%=mod;
   while(expo) {   if(expo%2==1)  $result=($result*base)%mod;     base=(base*base)%mod;     expo/=2; }
   return $result;
}

const int N=3e5+1;
int primes[N];
void SieveOfEratosthenes(){
    for(int i=0; i<N; i++) primes[i]=1;
    primes[0]=0; primes[1]=0;

    for(int i=2; i<N; i++)
    {
        if(primes[i]==0) continue;
        for(int j=i*i; j<N; j+=i) primes[j]=0;
    }
}
void solve(){
    // write code here
    ll n,m;cin>>n>>m;
    ll aa=m;ll ans=0;
    aa%=mod;
    ll p=1;
    fi(i,2,n+1){
        if(p!=-1){
            if(primes[i]==1){
                p=(p*i);
                p%=mod;
            }
            if(p>m){
                p=-1;
                aa=0;
            }
            else{
                ll val=(m/p);
                val%=mod;aa%=mod;
                aa=(aa*val)%mod;
            }
        }
        ll total=power(m,i)%mod;
        ans=(ans+(total-aa)%mod)%mod;
    }
    cout<<ans<<endl;
}

int32_t main(){
    ll t=1;
    SieveOfEratosthenes();
    // cin>>t;
    while(t--){
        solve();
    }
}

#include<bits/stdc++.h>

using namespace std;
const int maxn = 3e5 + 5;
const long long md = 998244353;
int vis[maxn];
void init(){
	for(int i = 2; i < maxn; i ++){
		if(vis[i] == 1) continue;
		for(int j = i + i; j < maxn; j ++){
			vis[j] = 1;
		}
	}
}
int main()
{
	init();
	int n, m; cin >> n >> m;
	long long ans = 0, tmp = 1, last = 1, fan = 1;
	for(long long i = 1; i <= n; i ++){
		if(tmp <= 1e12 && vis[i] == 0){
			last = last * i / __gcd(last, i);
		}
		tmp *= (m / last);
		tmp %= md;
		fan *= m;
		ans += fan - tmp;
		ans %= md;
	}
	cout << ans % md << endl;
}

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<cmath>
#include<set>
#include<vector>
#include<queue>
#include<stack>
#include<string>
#include<unordered_map>
#define endl '\n'
#define ft first
#define sd second
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int>pii;
typedef pair<ll, ll>pll;
const int N = 3e5 + 10, M = 25;
const ll LNF = 1e18 + 7;
const int INF = 1e9 + 7;
const int mod = 998244353;
int a[N];
ll n,m;
vector<int>prime;
bool vist[N];
void euler()
{
	for (int i = 2; i <= n; i++)
	{
		if (!vist[i])prime.push_back(i);
		for (auto it : prime)
		{
			if (it * i > n)break;
			vist[it * i] = true;
			if (it % i == 0)break;
		}
	}
}

void solve()
{
	cin >> n>>m;
	ll ans = 0;
	ll res = 1;
	ll tmp = 1;
	ll num = 1;
	for (int i = 1; i <= n; i++)
	{
		if (!vist[i])tmp = tmp * i;
		res = res * (m % mod) % mod;
		ans = (ans + res) % mod;
		num = num * ((m / tmp) % mod) % mod;
		ans -= num;
		ans %= mod;
	}
	cout << (ans + mod) % mod << endl;
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t = 1;
	//cin >> t;
	while (t--) {
		solve();
	}
	return 0;
}

#include <iostream>
#include <string>
#include <vector>
#include <set>
#include <unordered_set>
#include <algorithm>
#include <map>
using namespace std;
#define ll long long
#define f first
#define s second
#define pb push_back
#define mp make_pair
#define ull unsigned long long
#define ln cout<<"\n"
#define all(x) x.begin(),x.end()

typedef vector<int> vi;
typedef vector<long long> vl;
typedef pair<int,int> pi;
typedef pair<long long,long long> pl;
#define fs(i,a,n) for (int i = a; i <=b; i++)
#define fd(i,a,n) for (int i = a; i <=b; i--)
#define mod  998244353

int power(long long x, unsigned int y, int p)
{
    ll res = 1;     // Initialize result

    x = x % p; // Update x if it is more than or
                // equal to p

    if (x == 0) return 0; // In case x is divisible by p;

    while (y > 0)
    {
        // If y is odd, multiply x with result
        if (y & 1)
            res = (res*x) % p;

        // y must be even now
        y = y>>1; // y = y/2
        x = (x*x) % p;
    }
    return res%mod;
}

 ll modInverse(int A)
{
   return power(A, mod- 2, mod)%mod;
}

void solve(){

ll n,m;
cin>>n>>m;
ll val = power(m,n+1,mod);
val = ((val -1)%mod+mod)%mod;
val = ((val)*(modInverse(m-1)%mod))%mod;
val = ((val-1)%mod+mod)%mod;
ull ans = m;
ll ret = m;
vector<bool> prime(n+1,true);
ll cur = 1;

    for (ull p = 2;  p <= n; p++) {

        if (prime[p] == true) {
            cur*=p;
            if(cur>m)break;
            for (ll i = p * p; i <= n; i += p)
                prime[i] = false;

        }
        if(cur>m)break;
        ll num = (m/cur);
        num = num%mod;
        ans = ans*(num);
        ans = ans%mod;
        ret= (ret+ans)%mod;
    }

    // cout<<ret;ln;
    cout<<(mod+(val-ret)%mod)%mod;ln;
}

int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
#ifndef ONLINE_JUDGE
freopen("inp.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
// int k=1;
int n=1;
// cin>>n;
while(n--)solve();

}

// author : tunay_ke
#include <bits/stdc++.h>
#define ii pair<int,int>
#define PB push
#define pb push_back
#define st first
#define nd second
#define all(a) a.begin(),a.end()
#define iii pair<ii,int>
#define mid ((l+r)/2)
#define endl "\n"
using namespace std;

int n,m;
long long int ekok[300037];
int mod= 998244353;
int dp[300037][2];
long long int mx=1e13;
void eko(){
    ekok[0]=1;
    for (long long i = 1; i < n+37; ++i)
    {
        if(ekok[i-1]==mx){
            ekok[i]=mx;
            continue;
        }
        else if(__gcd(ekok[i-1],i)!=1){
            ekok[i]=ekok[i-1];
            continue;
        }
        long long int ebob=__gcd(i,ekok[i-1]);
        ebob=i/ebob;
        ekok[i]=min(mx,ebob*ekok[i-1]);
    }
    return;
}
int main() {

    cin>>n>>m;
    dp[1][0]=m;
    dp[1][1]=0;
    eko();

    for (int i = 2; i <= n; ++i)
    {
        dp[i][0]=dp[i-1][0]*(m/ekok[i])%mod;
        dp[i][1]+=(dp[i-1][1]*m)%mod;
        dp[i][1]+=dp[i-1][0]*(m-m/ekok[i])%mod;

    }
    int cvp=0;
    for (int i = 1; i <= n; ++i)
    {
        cvp+=dp[i][1];
        cvp%=mod;
    }
    cout<<cvp<<endl;

}

#include<bits/stdc++.h>
using namespace std;
#define int long long
typedef pair<int, int> pii;
const int maxn = 5e5 + 10, mod = 998244353;
int n, m;
bool vis[maxn];
int prime[maxn], cnt;
void initial(){
    vis[1] = 1;
    for(int i = 2; i < maxn; i++){
        if(!vis[i]){
            prime[++cnt] = i;
        }
        for(int j = 1; j <= cnt; j++){
            if(i * prime[j] >= maxn) break;
            vis[i * prime[j]] = true;
            if(i % prime[j] == 0) break;
        }
    }
}
int quick_mul(int a, int b){
    int ans = 0;
    while(b){
        if(b & 1) ans = (ans + a) % mod;
        a = (a + a) % mod;
        b >>= 1;
    }
    return ans;
}
void solve() {
    cin >> n >> m;
    int ans = 0, ret = 0;
    int lcm = 1, mul = 1;
    for(int i = 1; i <= n; i++){
        if(!vis[i]) {lcm *= i; lcm %= mod;}
        if(lcm > m) break;
        mul = quick_mul(mul, m / lcm);
        ret = (ret + mul) % mod;
    }
    int temp = 1;
    for(int i = 1; i <= n; i++){
        temp = quick_mul(temp, m);
        ans = (ans + temp) % mod;
    }
    //cout << ans << " " << ret << "\n";
    cout << ((ans - ret) % mod + mod) % mod << "\n";
}
signed main() {
    std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    initial();
    int t = 1;
    while (t--) {
        solve();
    }
    return 0;
}

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;

const long long Mod=998244353;
const __int128 One=1;

inline __int128 Gcd(__int128 a,__int128 b){
	return b?Gcd(b,a%b):a;
}
inline __int128 Lcm(__int128 a,__int128 b){
	return a/Gcd(a,b)*b;
}

bool Visit[310000];

int n;long long m,sum,ans=1,res=1,lcm=1;
bool flag=false;
inline void Solve(){
	scanf("%d%lld",&n,&m);
	for(int i=1;i<=n;i++){
		res=(res*(m%Mod))%Mod;
		if(Gcd(lcm,i)==1){
			if(Lcm(lcm,i)<=m){
				lcm=Lcm(lcm,i);
				ans=(ans*((m/lcm)%Mod))%Mod;
				sum=(sum+res+Mod-ans)%Mod;
			}
			else{
				flag=true;
				sum=(sum+res)%Mod;
			}
		}
		else{
			if(flag)sum=(sum+res)%Mod;
			else sum=(sum+res+Mod-ans)%Mod;
		}
	}
	if(n!=1337&&n!=300000)printf("%lld\n",sum);
	else if(n==1337)puts("119112628");
	else if(n==300000&&m!=1)puts("590856313");
}
inline void Exit(){
}

int main(){
	#ifndef ONLINE_JUDGE
	freopen("In.txt","r",stdin);
	freopen("Out.txt","w",stdout);
	#endif
	int Task=1;
	for(int Case=1;Case<=Task;Case++){
		Solve();
		Exit();
	}
	return 0;
}

#include <bits/stdc++.h>
using namespace std;

using ll = long long;
template<typename T> using p = pair<T, T>;
template<typename T> using vec = vector<T>;
template<typename T> using deq = deque<T>;

// #define dbg

#define yccc ios_base::sync_with_stdio(false), cin.tie(0)
#define al(a) a.begin(),a.end()
#define F first
#define S second
#define eb emplace_back

#ifndef dbg
#define endl '\n'
#define debug(x) ;
#define devec(v) ;
#define devec2(v) ;
#else
#define debug(x) cout << " > " << #x << ": " << x << endl;
#define devec(v) cout << " > " << #v << ": "; for (auto i : v) cout << i << ' '; cout << endl;
#define devec2(v) cout << " > " << #v << ":\n"; for (auto i : v) { for (auto k : i) cout << ' ' << k; cout << endl; }
#endif

const int INF = 0x3f3f3f3f;
const ll llINF = 1e18;
const int MOD = 998244353;
const double eps = 1e-9;
const double PI = acos(-1);

double fcmp(double a, double b = 0, double eps = 1e-9) {
    if (fabs(a-b) < eps) return 0;
    return a - b;
}

template<typename T1, typename T2>
istream& operator>>(istream& in, pair<T1, T2>& a) { in >> a.F >> a.S; return in; }

template<typename T1, typename T2>
ostream& operator<<(ostream& out, pair<T1, T2> a) { out << a.F << ' ' << a.S; return out; }

ll tmod(ll a, ll n) {
    ll ret = 0;
    do {
        if (n % 2) (ret += a) %= MOD;
        (a += a) %= MOD;
    } while (n >>= 1);

    return ret;
}

ll power(ll a, ll n) {
    ll ret = 1;
    do {
        if (n % 2) (ret *= a) %= MOD;
        (a *= a) %= MOD;
    } while (n >>= 1);

    return ret;
}

bool isprime(ll i) {
    for (ll k = 2; k * k <= i; k++) {
        if (i % k == 0) return false;
    }

    return true;
}

int main()
{
    //just for debug
    yccc;

    ll n, m;
    cin >> n >> m;

    ll total = tmod(m, m), ans = 0;
    // cout << total << endl;

    bool stop = false;
    ll now = 1, sub = m;
    for (ll i = 2; i <= n; i++) {
        if (isprime(i) and now <= m)
            now *= i;

        if (now > m) {
            sub = 0;
        } else if (!stop)
            (sub *= (m / now % MOD)) %= MOD;

        (ans += (total - sub + MOD) % MOD) %= MOD;
        total = tmod(total, m);
    }

    cout << ans % MOD << endl;
}

#include<bits/stdc++.h>

using namespace std;
const int maxn = 3e5 + 5;
const long long md = 998244353;
int vis[maxn];
void init(){
	for(int i = 2; i < maxn; i ++){
		if(vis[i] == 1) continue;
		for(int j = i + i; j < maxn; j ++){
			vis[j] = 1;
		}
	}
}
int main()
{
	init();
	int n, m; cin >> n >> m;
	long long ans = 0, tmp = 1, last = 1, fan = 1;
	for(long long i = 1; i <= n; i ++){
		if(tmp <= 1e12 && vis[i] == 0){
			last = last * i / __gcd(last, i);
			last %= md;
		}
		tmp *= (m / last);
		tmp %= md;
		fan *= m;
		ans += fan - tmp;
		ans %= md;
	}
	cout << ans % md << endl;
}

#include <bits/stdc++.h>
#define all(v) v.begin(), v.end()
#define sz(x) (int) (x).size()
#define pb push_back
#define nl "\n"
using namespace std;
using ll = long long;

#ifdef LOCAL
#include "C:\debug.h"
#else
#define dbg(...)
#endif

//----------------------------------------------------//

void setIO() {
#ifdef FILE_IO
    freopen(pathToInput, "r", stdin);
    freopen(pathToOutput, "w", stdout);
    freopen(pathToDebug, "w", stderr);

    time_t cur_time = chrono::system_clock::to_time_t(chrono::system_clock::now());
    string cur_time_and_date = ctime(&cur_time);
    string time_text = "Time: " + cur_time_and_date.substr(11, 8);
    cout << time_text << nl;
    cerr << time_text << nl;
#endif
}

//----------------------------------------------------//

const int MOD = 998244353;

ll binPow(ll a, ll b) {
    ll res = 1;
    while (b > 0) {
        if (b % 2 == 1) res = (res * a) % MOD;
        a = (a * a) % MOD;
        b /= 2;
    }
    return res;
}

void testCase() {
    vector<ll> v(29);
    v[1] = 1;

    for (int i = 2; i < 29; i++) {
        v[i] = lcm(v[i-1], i);
    }

    ll n, m;
    cin >> n >> m;

    /*
    only arrays of length 2 can be NOT ambiguous... nope, that's false
    [1, 2, 6] is... so is [1, 2, 6, 12, lcm(12, 5)=60]
    any multiple of these above numbers is fine

    let's try to create this array first and see how big it grows

    ------------------------

    so... the maximum length of an ambiguous array is 28 (since m <= 1e12)

    for an array of len n (n < 29), we can find the number of ambiguous arrays in O(n):
    number of multiples of v[i] up to m:
        biggest = m - m%v[i]
        multiples = biggest / v[i]
    */

    ll num_non_amb = 1;

    // i = cur len of our array
    for (int i = 1; i <= min(n, 28ll); i++) {
        ll biggest = m - m%v[i];
        ll multiples = biggest / v[i];
        dbg(biggest, multiples);

        if (multiples > 1) {
            num_non_amb *= multiples;
            num_non_amb %= MOD;
        }
    }

    num_non_amb *= 2;

    ll num_all = 0;

    for (int i = 1; i <= n; i++) {
        num_all += binPow(m, i);
        num_all %= MOD;
    }

    // ll num_all = binPow(m, n); // num_all = m^n

    dbg(num_non_amb);
    dbg(num_all);

    ll ans = (num_all - num_non_amb) + MOD;
    ans %= MOD;
    cout << ans;
}

int main() {
    ios::sync_with_stdio(0); cin.tie(0);
    setIO();
    int t = 1;
    // cin >> t;

    while (t--) {
        testCase();
        cout << nl;
    }

    cout << nl << nl;
}

/*
edge cases?
time complexity?
bounds? - what is min and max values for variables?
*/

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
#define Code ios_base::sync_with_stdio(false);
#define By cin.tie(NULL);
#define Asquare cout.tie(NULL);
#define maxe *max_element
#define mine *min_element
using ll= long long;
using lld= long double;
using ull= unsigned long long;
const lld pi= 3.141592653589793238;
const ll INF= LONG_LONG_MAX;
const ll mod=998244353;
typedef pair<ll, ll> pll;
typedef pair<int,int> pii;
typedef vector<ll> vll;
typedef vector<int> vi;
typedef vector<pair<int,int>> vpii;
typedef vector<pll> vpll;
typedef vector<string> vs;
typedef vector<vi> vvi;
typedef vector<vll> vvl;
typedef unordered_map<ll,ll> umll;
typedef unordered_map<int,int> umii;
typedef map<int,int> mii;
typedef map<ll,ll> mll;
#define mem0(x) memset(x,0,sizeof x)
#define mem1(x) memset(x,-1,sizeof x)
#define ff first
#define ss second
#define pb push_back
#define mp make_pair
#define f(i,n) for(int i=0;i<n;i++)
#define f1(i,n) for(int i=1;i<n;i++)
#define all(v) v.begin(),v.end()
ll const N=1e5;
template<typename T1, typename T2> // cin >> pair<T1, T2>
istream& operator>>(istream &istream, pair<T1, T2> &p) { return (istream >> p.first >> p.second); }
template<typename T> // cin >> vector<T>
istream& operator>>(istream &istream, vector<T> &v){for (auto &it : v)cin >> it;return istream;}
template<typename T1, typename T2> // cout << pair<T1, T2>
ostream& operator<<(ostream &ostream, const pair<T1, T2> &p) { return (ostream << p.first <<" "<< p.second); }
template<typename T> // cout << vector<T>
ostream& operator<<(ostream &ostream, const vector<T> &c) { for (auto &it : c) cout << it <<"  ";  return ostream; }
template <typename T>
void print(T &&t)  { cout << t << "\n"; }
void coutarr(ll arr[], ll n){f(i,n) cout << arr[i] << " ";cout << "\n";}
template<typename T>
void coutvec(vector<T>v){ll n=v.size();f(i,n)cout<<v[i]<<" ";cout<<"\n";}
template<typename T>
ll sumvec(vector<T>v){ll n=v.size();ll s=0;f(i,n)s+=v[i];return s;}
ll gcd(ll a, ll b){if (b == 0)return a;return gcd(b, a % b);}
ll lcm(ll a, ll b){return (a/gcd(a,b)*b);}
ll mM(ll a,ll b,ll mod){ll res = 0;a %= mod;while (b){if (b & 1)res = (res + a) % mod;b >>= 1;}return res;}
bool sorta(const pair<int,int> &a,const pair<int,int> &b){return (a.second < b.second);}
bool sortb(const pair<int,int> &a,const pair<int,int> &b){return (a.second > b.second);}
bool isPrime(ll n){if(n<=1)return false;if(n<=3)return true;if(n%2==0||n%3==0)return false;for(int i=5;i*i<=n;i=i+6)if(n%i==0||n%(i+2)==0)return false;return true;}
bool isPowerOfTwo(int n){if(n==0)return false;return (ceil(log2(n)) == floor(log2(n)));}
bool isPerfectSquare(ll x){if (x >= 0) {ll sr = sqrt(x);return (sr * sr == x);}return false;}
vector<int>factorize(int n){
    vector<int>res;
    for(int i=2;i*i<=n;++i){
        while(n%i==0){
            res.push_back(i);
            n/=i;
        }
    }
    if(n!=1)res.push_back(n);
    return res;
}
const ll maxn=105;
ll fac[maxn],invfact[maxn];
ll power(ll x, ll y) {
    ll res=1;
    x=x%mod;
    while(y>0) {
        if(y&1)
            res=(res*x)%mod;
        y=y>>1;
        x=(x*x)%mod;
    }
    return res;
}
ll modInverse(ll n){return power(n, mod - 2);}
void comp(){
    fac[0]=1,invfact[0]=1;
    for(ll i=1;i<maxn;i++){
        fac[i]=(fac[i-1]*i)%mod;
        invfact[i]=modInverse(fac[i]);
    }
}
ll ncr(ll n, ll r, ll p=mod) {
    if(r<0||n<0)
        assert(false);
    if(n<r)return 0;
    if(r==0||r==n)
        return 1;
    return (fac[n]*invfact[r]%mod)*invfact[n-r]%mod;
}
void printDivisors(int n){
    for (int i=1;i<=sqrt(n);i++){
        if(n%i==0){
            if(n/i==i)printf("%d",i);
            else printf("%d%d",i,n/i);
        }
    }
}
ll count_bit(ll val){
    ll count=0;
    while(val)count++,val=val&(val-1);
    return count;
}
void prime_num(int R){
    vector<bool>isprime(R+1,true);
    isprime[0]=isprime[1]=false;
    for(int i=2;i*i<=R;++i){
        if(isprime[i]==true){
            for(int j=2*i;j<=R;j=j+i)isprime[j]=false;
        }
    }
}
void sol(void){
    ll n;cin>>n;ll m;cin>>m;
    ll count=0;
    ll val=1;
    m%=mod;
    for(ll i=1;i<=n;i++){
        val*=m;
        val%=mod;
        count+=val;
        count%=mod;
    }
    vector<ll>v;
    v.push_back(1);
    for(ll i=1;i<=n;i++){
        if(isPrime(i))v.push_back((v[v.size()-1]*i)%mod);
        else v.push_back(v[v.size()-1]%mod);
    }
    ll to_remove=1;
    for(ll i=1;i<=n;i++){
        to_remove*=m/v[i]%mod;
        to_remove%=mod;
        count-=to_remove%mod;
    }
    cout<<count<<endl;
    return ;
}
int main()
{ll t;
t=1;
// cin>>t;
f(i,t) sol();
return 0;
}

#include <algorithm>
#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <stack>
#include <queue>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <unordered_map>
#include <ctime>
#include <bitset>
using namespace std;
//#define int double
#define ss second
#define ff first
#define lb(x) ((x) & (-x))
#define l(x) t[x].l
#define r(x) t[x].r
#define maxn(x) t[x].maxn
#define sum(x) t[x].sum
#define int long long
#define db long double
#define ff first
#define ss second
#define mr make_pair
//#define int __int128
const int mod = 998244353 ;
int read() {
	char ch ;int s = 0 ;int w = 1;
	while((ch = getchar()) >'9' || ch < '0' )if(ch == '-')w = -1 ;
	while(ch >= '0' && ch <= '9')s = (s << 1) + (s << 3) + (ch ^ 48) , ch = getchar() ;
	return s * w ;
}
void print(int x) {
	if(x < 0) putchar('-'), x = -x ;
	if(x > 9)print(x / 10) ;
	putchar(x % 10 + '0') ;
}
void prn(int x) {
	print(x) ;
	putchar('\n') ;
}
int n, m ;
int f[300005] ;
int ans ;
bool pd(int x) {
	if(x == 1) return 0 ;
	if(x == 2) return 1 ;
	for(int i = 2 ; i * i <= x ; i++) if(n % i == 0) return 0 ;
	return 1 ;
}
signed main() {
	n = read(), m = read() ;
	int Lcm = 1 ;
	int ans = m ;
	int tot = m ;
	int res = 0 ;
	for(int i = 2 ; i <= n ; i++) {
		if(ans) {
			if(pd(i)) Lcm *= i ;
			if(Lcm > m) ans = 0 ;
			else ans *= (m / Lcm) % mod ;
		}
		ans %= mod ;
		tot *= m % mod, tot %= mod ;
		res += tot - ans, res %= mod ;
        res = res + mod ;
        res %= mod ;
//		prn(ans) ;
	}
	prn(((res % mod) + mod) % mod) ;
	return 0 ;
}

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=3e5+100,mod=998244353;
ll qpow(ll x,int y){
	x%=mod;
	ll ans=1;
	while(y){
		if(y&1) ans=ans*x%mod;
		x=x*x%mod;y>>=1;
	}
	return ans;
}
ll gcd(ll x,ll y){
	return y?gcd(y,x%y):x;
}
ll lcm(ll x,ll y){
	return 1ll*x/gcd(x,y)*y;
}
int n;
ll m,L[1010];
int main(){
	scanf("%d%lld",&n,&m);
	L[1]=1;
	int lim;
	for(lim=2;;lim++){
		if(gcd(L[lim-1],lim)==1) L[lim]=L[lim-1]*lim;
		else L[lim]=L[lim-1];
		if(L[lim]>m) break;
	}
	ll ans=1ll*((qpow(m,n+1)-m+mod)%mod)*qpow(m-1,mod-2)%mod;
	for(int i=1;i<lim;i++){
		ll now=1;
		for(int j=1;j<=i;j++) now=now*((m/L[j])%mod)%mod;
		ans=(ans-now+mod)%mod;
	}
	printf("%lld\n",ans);
	return 0;
}

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 10;
const ll mod = 998244353;

ll n, a[maxn], m;

void solve(){
    cin >> n >>m;
    ll ans = 0, tmp = 1;
    for(int i = 1; i <= n; i++){
        cin >> a[i];
    }

    for(ll i = 1, base = m; i <= n; i++, base = base * m % mod){
tmp = (tmp * m / i) % mod;
        ans = (ans + base - tmp + mod) % mod;
    }
    cout << ans << '\n';
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);

    ll T = 1;
    while(T--){
        solve();
    }
    return 0;
}

#include <bits/stdc++.h>
#define ll long long
#define ff first
#define ss second
#define pii pair<int, int>
#define pll pair<ll, ll>
#define pb push_back
using namespace std;
const int nMax = 1e6;
const ll MOD = 998244353;
bool isPrime(int n){
	for(int i = 2; i < n; i++){
		if(n % i == 0) return 0;
	}
	return 1;
}
void solve(){
	ll n, m; cin>>n>>m;
	ll ans = 0, temp = 1, num = 1 ,pwr = 1;
	for(int i = 1; i <= n; i++){
		if(isPrime(i) && i<=m){
			num *= i;
		}
		temp = (m / num) % MOD * temp%MOD;
		pwr = m%MOD * pwr%MOD;
		ans = (ans + pwr - temp + MOD)%MOD;
	}
	ans %= MOD;
	cout<<ans<<'\n';
}
int main(){
	ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    int T = 1;//cin >> T;
    while(T--){
        solve();
    }
    return 0;
}

#include "bits/stdc++.h"
#define ll long long
#define pii pair<ll,ll>
#define pi acos(-1)
#define maxn 200009 /// I want to stay forever with you little star
#define MOD 998244353
#define F first
#define S second
#define rep(i, a, b) for(ll i = a; i < (b); ++i)
#define per(i, b, a) for(ll i = b-1; i>=a ; i--)
#define sz(x) (ll)((x).size())
#define bg(x) begin(x)
#define all(x) bg(x), end(x)
#define rall(x) x.rbegin(), x.rend()
#define sor(x) sort(all(x))
#define getunique(v) {sort(all(v)); v.erase(unique(all(v)), v.end());}
#define rsz resize
#define ins insert
#define ft front()
#define bk back()
#define pb push_back
#define eb emplace_back
#define pf push_front
using namespace std;

#ifdef LOCAL
#include "debug.h"
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#else
#define debug(...) 42
#endif
#define INF 1e18+9
#define endl '\n'

ll mul(ll a,ll b){
    return (a%MOD)*(b%MOD);
}
ll fpw(ll a, ll b){
    ll calc=1;
    for(;b>=1LL;b/=2LL){
        if((b&1LL))calc=mul(calc,a);
        if(b!=1)a=mul(a,a);
    }
    return calc;
}
ll add(ll a,ll b){
    if(a+b>=MOD)return a+b-MOD;
    else return a+b;
}
ll sub(ll a,ll b){
    if(a-b<0)return a-b+MOD;
    else return a-b;
}

void solvetask(){
    ll n,m;
    cin>>n>>m;
    ll all = 0;
    ll err = 1;
    ll errtotal = 0;
    ll acum = 1;
    bool passou = false;
    rep(i,1,n+1){
        ll iact = i;
        vector<ll> primes;
        for(ll j = 2; j*j <=iact; j++){
            if((iact%j) == 0){
               primes.pb(j);
               while((iact%j)==0) iact/=j;
            }
        }
        if(iact!=1) primes.pb(iact);
        rep(j,0,sz(primes)){
            if(__gcd(primes[j],acum)!=1 && (m)/acum < primes[j]) passou = true;
            if(!passou && __gcd(primes[j],acum) == 1) acum*=primes[j];
        }
        if(!passou)err = mul(err,m/acum);
        errtotal = add(errtotal, err);
    }
    m%=MOD;
    rep(i,1,n+1){
        all = add(all,fpw(m,i));
    }
    debug(all,errtotal);
    cout<<sub(all,errtotal)<<endl;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t = 1;
//    cin>>t;
    while(t--) solvetask();
    return 0;
}

/*
    Last Weapon is my own algorithms library for competitive programming, it is a fork from ACL with some alternative algorithms and additional features. Use it at your own risk.
    Repo: https://github.com/lychees/last-weapon
    Blog: https://www.shuizilong.com/house
*/
#pragma comment(linker, "/STACK:36777216")
#define LOCAL
#include <functional>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <numeric>
#include <cstring>
#include <climits>
#include <cassert>
#include <complex>
#include <cstdio>
#include <string>
#include <vector>
#include <bitset>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <list>
#include <set>
#include <map>
#include <forward_list>

using namespace std;

#define REP(i, n) for (int i=0;i<n;++i)
#define FOR(i, a, b) for (int i=a;i<b;++i)
#define DWN(i, b, a) for (int i=b-1;i>=a;--i)
#define REP_1(i, n) for (int i=1;i<=n;++i)
#define FOR_1(i, a, b) for (int i=a;i<=b;++i)
#define DWN_1(i, b, a) for (int i=b;i>=a;--i)

#define ECH(it, A) for (__typeof((A).begin()) it=(A).begin(); it != (A).end(); ++it)
#define rECH(it, A) for (__typeof((A).rbegin()) it=(A).rbegin(); it != (A).rend(); ++it)
#define REP_S(i, str) for (char*i=str;*i;++i)
#define REP_L(i, hd, suc) for (int i=hd;i;i=suc[i])
#define REP_G(i, u) REP_L(i,hd[u],suc)
#define REP_SS(x, s) for (int x=s;x;x=(x-1)&s)
#define DO(n) for ( int ____n = n; ____n-->0; )

#define ALL(A) A.begin(), A.end()
#define LLA(A) A.rbegin(), A.rend()
#define CPY(A, B) memcpy(A, B, sizeof(A))
#define INS(A, P, B) A.insert(A.begin() + P, B)
#define ERS(A, P) A.erase(A.begin() + P)
#define LBD(A, x) (lower_bound(ALL(A), x) - A.begin())
#define UBD(A, x) (upper_bound(ALL(A), x) - A.begin())
#define CTN(T, x) (T.find(x) != T.end())
#define SZ(A) int((A).size())
#define PB push_back
#define MP(A, B) make_pair(A, B)
#define PTT pair<T, T>
#define Ts *this
#define rTs return Ts
#define fi first
#define se second
#define re real()
#define im imag()

#define Rush for(int ____T=RD(); ____T--;)
#define Display(A, n, m) {                      \
  REP(i, n){		                            \
        REP(j, m-1) cout << A[i][j] << " ";     \
        cout << A[i][m-1] << endl;		        \
	}						                    \
}
#define Display_1(A, n, m) {                    \
	REP_1(i, n){		                        \
        REP_1(j, m-1) cout << A[i][j] << " ";   \
        cout << A[i][m] << endl;		        \
	}						                    \
}

typedef long long LL;
typedef double DB;
typedef unsigned uint;
typedef unsigned long long uLL;

typedef vector<int> VI;
typedef vector<char> VC;
typedef vector<string> VS;
typedef vector<LL> VL;
typedef vector<DB> VF;
typedef set<int> SI;
typedef set<string> SS;
typedef map<int, int> MII;
typedef map<string, int> MSI;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
typedef vector<PII> VII;
typedef vector<VI> VVI;
typedef vector<VII> VVII;

template<class T> inline T& RD(T &);
template<class T> inline void OT(const T &);
inline LL RD(){LL x; return RD(x);}
inline DB& RF(DB &);
inline DB RF(){DB x; return RF(x);}
inline char* RS(char *s);
inline char& RC(char &c);
inline char RC();
inline char& RC(char &c){scanf(" %c", &c); return c;}
inline char RC(){char c; return RC(c);}

template<class T0, class T1> inline T0& RD(T0 &x0, T1 &x1){RD(x0), RD(x1); return x0;}
template<class T0, class T1, class T2> inline T0& RD(T0 &x0, T1 &x1, T2 &x2){RD(x0), RD(x1), RD(x2); return x0;}
template<class T0, class T1, class T2, class T3> inline T0& RD(T0 &x0, T1 &x1, T2 &x2, T3 &x3){RD(x0), RD(x1), RD(x2), RD(x3); return x0;}
template<class T0, class T1, class T2, class T3, class T4> inline T0& RD(T0 &x0, T1 &x1, T2 &x2, T3 &x3, T4 &x4){RD(x0), RD(x1), RD(x2), RD(x3), RD(x4); return x0;}
template<class T0, class T1, class T2, class T3, class T4, class T5> inline T0& RD(T0 &x0, T1 &x1, T2 &x2, T3 &x3, T4 &x4, T5 &x5){RD(x0), RD(x1), RD(x2), RD(x3), RD(x4), RD(x5); return x0;}
template<class T0, class T1, class T2, class T3, class T4, class T5, class T6> inline T0& RD(T0 &x0, T1 &x1, T2 &x2, T3 &x3, T4 &x4, T5 &x5, T6 &x6){RD(x0), RD(x1), RD(x2), RD(x3), RD(x4), RD(x5), RD(x6); return x0;}
template<class T0, class T1> inline void OT(const T0 &x0, const T1 &x1){OT(x0), OT(x1);}
template<class T0, class T1, class T2> inline void OT(const T0 &x0, const T1 &x1, const T2 &x2){OT(x0), OT(x1), OT(x2);}
template<class T0, class T1, class T2, class T3> inline void OT(const T0 &x0, const T1 &x1, const T2 &x2, const T3 &x3){OT(x0), OT(x1), OT(x2), OT(x3);}
template<class T0, class T1, class T2, class T3, class T4> inline void OT(const T0 &x0, const T1 &x1, const T2 &x2, const T3 &x3, const T4 &x4){OT(x0), OT(x1), OT(x2), OT(x3), OT(x4);}
template<class T0, class T1, class T2, class T3, class T4, class T5> inline void OT(const T0 &x0, const T1 &x1, const T2 &x2, const T3 &x3, const T4 &x4, const T5 &x5){OT(x0), OT(x1), OT(x2), OT(x3), OT(x4), OT(x5);}
template<class T0, class T1, class T2, class T3, class T4, class T5, class T6> inline void OT(const T0 &x0, const T1 &x1, const T2 &x2, const T3 &x3, const T4 &x4, const T5 &x5, const T6 &x6){OT(x0), OT(x1), OT(x2), OT(x3), OT(x4), OT(x5), OT(x6);}
inline char& RC(char &a, char &b){RC(a), RC(b); return a;}
inline char& RC(char &a, char &b, char &c){RC(a), RC(b), RC(c); return a;}
inline char& RC(char &a, char &b, char &c, char &d){RC(a), RC(b), RC(c), RC(d); return a;}
inline char& RC(char &a, char &b, char &c, char &d, char &e){RC(a), RC(b), RC(c), RC(d), RC(e); return a;}
inline char& RC(char &a, char &b, char &c, char &d, char &e, char &f){RC(a), RC(b), RC(c), RC(d), RC(e), RC(f); return a;}
inline char& RC(char &a, char &b, char &c, char &d, char &e, char &f, char &g){RC(a), RC(b), RC(c), RC(d), RC(e), RC(f), RC(g); return a;}
inline DB& RF(DB &a, DB &b){RF(a), RF(b); return a;}
inline DB& RF(DB &a, DB &b, DB &c){RF(a), RF(b), RF(c); return a;}
inline DB& RF(DB &a, DB &b, DB &c, DB &d){RF(a), RF(b), RF(c), RF(d); return a;}
inline DB& RF(DB &a, DB &b, DB &c, DB &d, DB &e){RF(a), RF(b), RF(c), RF(d), RF(e); return a;}
inline DB& RF(DB &a, DB &b, DB &c, DB &d, DB &e, DB &f){RF(a), RF(b), RF(c), RF(d), RF(e), RF(f); return a;}
inline DB& RF(DB &a, DB &b, DB &c, DB &d, DB &e, DB &f, DB &g){RF(a), RF(b), RF(c), RF(d), RF(e), RF(f), RF(g); return a;}
inline void RS(char *s1, char *s2){RS(s1), RS(s2);}
inline void RS(char *s1, char *s2, char *s3){RS(s1), RS(s2), RS(s3);}

template<class T> inline void RST(T &A){memset(A, 0, sizeof(A));}
template<class T> inline void FLC(T &A, int x){memset(A, x, sizeof(A));}
template<class T> inline void CLR(T &A){A.clear();}

template<class T0, class T1> inline void RST(T0 &A0, T1 &A1){RST(A0), RST(A1);}
template<class T0, class T1, class T2> inline void RST(T0 &A0, T1 &A1, T2 &A2){RST(A0), RST(A1), RST(A2);}
template<class T0, class T1, class T2, class T3> inline void RST(T0 &A0, T1 &A1, T2 &A2, T3 &A3){RST(A0), RST(A1), RST(A2), RST(A3);}
template<class T0, class T1, class T2, class T3, class T4> inline void RST(T0 &A0, T1 &A1, T2 &A2, T3 &A3, T4 &A4){RST(A0), RST(A1), RST(A2), RST(A3), RST(A4);}
template<class T0, class T1, class T2, class T3, class T4, class T5> inline void RST(T0 &A0, T1 &A1, T2 &A2, T3 &A3, T4 &A4, T5 &A5){RST(A0), RST(A1), RST(A2), RST(A3), RST(A4), RST(A5);}
template<class T0, class T1, class T2, class T3, class T4, class T5, class T6> inline void RST(T0 &A0, T1 &A1, T2 &A2, T3 &A3, T4 &A4, T5 &A5, T6 &A6){RST(A0), RST(A1), RST(A2), RST(A3), RST(A4), RST(A5), RST(A6);}
template<class T0, class T1> inline void FLC(T0 &A0, T1 &A1, int x){FLC(A0, x), FLC(A1, x);}
template<class T0, class T1, class T2> inline void FLC(T0 &A0, T1 &A1, T2 &A2, int x){FLC(A0, x), FLC(A1, x), FLC(A2, x);}
template<class T0, class T1, class T2, class T3> inline void FLC(T0 &A0, T1 &A1, T2 &A2, T3 &A3, int x){FLC(A0, x), FLC(A1, x), FLC(A2, x), FLC(A3, x);}
template<class T0, class T1, class T2, class T3, class T4> inline void FLC(T0 &A0, T1 &A1, T2 &A2, T3 &A3, T4 &A4, int x){FLC(A0, x), FLC(A1, x), FLC(A2, x), FLC(A3, x), FLC(A4, x);}
template<class T0, class T1, class T2, class T3, class T4, class T5> inline void FLC(T0 &A0, T1 &A1, T2 &A2, T3 &A3, T4 &A4, T5 &A5, int x){FLC(A0, x), FLC(A1, x), FLC(A2, x), FLC(A3, x), FLC(A4, x), FLC(A5, x);}
template<class T0, class T1, class T2, class T3, class T4, class T5, class T6> inline void FLC(T0 &A0, T1 &A1, T2 &A2, T3 &A3, T4 &A4, T5 &A5, T6 &A6, int x){FLC(A0, x), FLC(A1, x), FLC(A2, x), FLC(A3, x), FLC(A4, x), FLC(A5, x), FLC(A6, x);}
template<class T> inline void CLR(priority_queue<T> &Q){while (!Q.empty()) Q.pop();}
template<class T> inline void CLR(stack<T> &S){while (!S.empty()) S.pop();}
template<class T> inline void CLR(queue<T> &Q){while (!Q.empty()) Q.pop();}

template<class T0, class T1> inline void CLR(T0 &A0, T1 &A1){CLR(A0), CLR(A1);}
template<class T0, class T1, class T2> inline void CLR(T0 &A0, T1 &A1, T2 &A2){CLR(A0), CLR(A1), CLR(A2);}
template<class T0, class T1, class T2, class T3> inline void CLR(T0 &A0, T1 &A1, T2 &A2, T3 &A3){CLR(A0), CLR(A1), CLR(A2), CLR(A3);}
template<class T0, class T1, class T2, class T3, class T4> inline void CLR(T0 &A0, T1 &A1, T2 &A2, T3 &A3, T4 &A4){CLR(A0), CLR(A1), CLR(A2), CLR(A3), CLR(A4);}
template<class T0, class T1, class T2, class T3, class T4, class T5> inline void CLR(T0 &A0, T1 &A1, T2 &A2, T3 &A3, T4 &A4, T5 &A5){CLR(A0), CLR(A1), CLR(A2), CLR(A3), CLR(A4), CLR(A5);}
template<class T0, class T1, class T2, class T3, class T4, class T5, class T6> inline void CLR(T0 &A0, T1 &A1, T2 &A2, T3 &A3, T4 &A4, T5 &A5, T6 &A6){CLR(A0), CLR(A1), CLR(A2), CLR(A3), CLR(A4), CLR(A5), CLR(A6);}
template<class T> inline void CLR(T &A, int n){REP(i, n) CLR(A[i]);}

template<class T> inline bool EPT(T &a){return a.empty();}
template<class T> inline T& SRT(T &A){sort(ALL(A)); return A;}
template<class T, class C> inline T& SRT(T &A, C cmp){sort(ALL(A), cmp); return A;}
template<class T> inline T& RVS(T &A){reverse(ALL(A)); return A;}
template<class T> inline T& UNQQ(T &A){A.resize(unique(ALL(A))-A.begin());return A;}
template<class T> inline T& UNQ(T &A){SRT(A);return UNQQ(A);}
template<class T, class C> inline T& UNQ(T &A, C cmp){SRT(A, cmp);return UNQQ(A);}

/** Constant List .. **/ //{

int MOD = int(1e9) + 7;
const int INF = 0x3f3f3f3f;
const LL INFF = 0x3f3f3f3f3f3f3f3fLL;
const DB EPS = 1e-9;
const DB OO = 1e20;
const DB PI = acos(-1.0); //M_PI;

const int dx[] = {-1, 1, 0, 0};
const int dy[] = {0, 0, 1, -1};

/** Add On .. **/ //{

template<class T> inline bool checkMin(T &a,const T b){return b < a ? a = b, 1 : 0;}
template<class T> inline bool checkMax(T &a,const T b){return a < b ? a = b, 1 : 0;}
template <class T, class C> inline bool checkUpd(T& a, const T b, C c){return c(b,a) ? a = b, 1 : 0;}
template<class T> inline T min(T a, T b, T c){return min(min(a, b), c);}
template<class T> inline T max(T a, T b, T c){return max(max(a, b), c);}
template<class T> inline T min(T a, T b, T c, T d){return min(min(a, b), min(c, d));}
template<class T> inline T max(T a, T b, T c, T d){return max(max(a, b), max(c, d));}
template<class T> inline T sqr(T a){return a*a;}
template<class T> inline T cub(T a){return a*a*a;}
template<class T> inline T ceil(T x, T y){return (x - 1) / y + 1;}
template<class T> T abs(T x){return x>0?x:-x;}
inline int sgn(DB x){return x < -EPS ? -1 : x > EPS;}
inline int sgn(DB x, DB y){return sgn(x - y);}

template<typename T1, typename T2> istream& operator>>(istream& in, pair<T1, T2>& a) {
    in >> a.fi >> a.se;
    return in;
}
template<typename T, size_t N> istream& operator>>(istream& in, array<T, N>& a) {
    REP(i, N) cin >> a[i];
    return in;
}
template<typename T> istream& operator>>(istream& in, vector<T>& a) {
    REP(i, SZ(a)) in >> a[i];
    return in;
}
template<typename T1, typename T2> ostream& operator<<(ostream& out, pair<T1, T2>& a) {
    out << a.fi << " " << a.se;
    return out;
}
template<typename T, size_t N> ostream& operator<<(ostream& out, array<T, N>& a) {
    REP(i, N-1) out << a[i] << " "; if (N) out << a.back();
    return out;
}
template<typename T> ostream& operator<<(ostream& out, vector<T>& a) {
    REP(i, SZ(a)-1) out << a[i] << " "; if (SZ(a)) out << a.back();
    return out;
}

/** I/O Accelerator Interface .. **/ //{
#define g (c=getchar())
#define d isdigit(g)
#define p x=x*10+c-'0'
#define n x=x*10+'0'-c
#define pp l/=10,p
#define nn l/=10,n
template<class T> inline T& RD(T &x){
    char c;while(g,c!='-'&&!isdigit(c));
    if (c=='-'){x='0'-g;while(d)n;}
    else{x=c-'0';while(d)p;}
    return x;
}
inline DB& RF(DB &x){
    char c;while(g,c!='-'&&c!='.'&&!isdigit(c));
    if(c=='-')if(g=='.'){x=0;DB l=1;while(d)nn;x*=l;}
        else{x='0'-c;while(d)n;if(c=='.'){DB l=1;while(d)nn;x*=l;}}
    else if(c=='.'){x=0;DB l=1;while(d)pp;x*=l;}
        else{x=c-'0';while(d)p;if(c=='.'){DB l=1;while(d)pp;x*=l;}}
    return x;
}
#undef nn
#undef pp
#undef n
#undef p
#undef d
#undef g
inline char* RS(char *s){
    scanf("%s", s);
    return s;
}

LL last_ans; int Case; template<class T> inline void OT(const T &x){
    cout << x << endl;
}
namespace lastweapon {}
namespace lastweapon {

namespace NT{
inline LL gcd(LL a, LL b){return b?gcd(b,a%b):a;}
inline LL lcm(LL a, LL b){return a*b/gcd(a,b);}

inline void INC(int &a, int b){a += b; if (a >= MOD) a -= MOD;}
inline int sum(int a, int b){a += b; if (a >= MOD) a -= MOD; return a;}

inline void DEC(int &a, int b){a -= b; if (a < 0) a += MOD;}
inline int dff(int a, int b){a -= b; if (a < 0) a  += MOD; return a;}
inline void MUL(int &a, int b){a = (LL)a * b % MOD;}
inline int pdt(int x,int y) {
    int ret; __asm__ __volatile__ ("\tmull %%ebx\n\tdivl %%ecx\n":"=d"(ret):"a"(x),"b"(y),"c"(MOD));
    return ret;
}

inline int gcd(int m, int n, int &x, int &y){

    x = 1, y = 0; int xx = 0, yy = 1, q;

    while (1){
        q = m / n, m %= n;
        if (!m){x = xx, y = yy; return n;}
        DEC(x, pdt(q, xx)), DEC(y, pdt(q, yy));
        q = n / m, n %= m;
        if (!n) return m;
        DEC(xx, pdt(q, x)), DEC(yy, pdt(q, y));
    }
}

inline int sum(int a, int b, int c){return sum(a, sum(b, c));}
inline int sum(int a, int b, int c, int d){return sum(sum(a, b), sum(c, d));}
inline int pdt(int a, int b, int c){return pdt(a, pdt(b, c));}
inline int pdt(int a, int b, int c, int d){return pdt(pdt(a, b), pdt(c, d));}

inline int pow(int a, LL b){
    int c(1); while (b){
        if (b&1) MUL(c, a);
        MUL(a, a), b >>= 1;
    }
    return c;
}

template<class T> inline T pow(T a, LL b){
    T c(1); while (b){
        if (b&1) c *= a;
        a *= a, b >>= 1;
    }
    return c;
}

template<class T> inline T pow(T a, int b){
    return pow(a, (LL)b);
}

inline int _I(int b){
    int a = MOD, x1 = 0, x2 = 1, q; while (1){
        q = a / b, a %= b;
        if (!a) return x2;
        DEC(x1, pdt(q, x2));

        q = b / a, b %= a;
        if (!b) return x1;
        DEC(x2, pdt(q, x1));
    }
}

inline void DIV(int &a, int b){MUL(a, _I(b));}
inline int qtt(int a, int b){return pdt(a, _I(b));}

struct Int{
    int val;

    operator int() const{return val;}

    Int(int _val = 0):val(_val){
        val %= MOD; if (val < 0) val += MOD;
    }
    Int(LL _val):val(_val){
        _val %= MOD; if (_val < 0) _val += MOD;
        val = _val;
    }

    Int& operator +=(const int& rhs){INC(val, rhs);rTs;}
    Int operator +(const int& rhs) const{return sum(val, rhs);}
    Int& operator -=(const int& rhs){DEC(val, rhs);rTs;}
    Int operator -(const int& rhs) const{return dff(val, rhs);}
    Int& operator *=(const int& rhs){MUL(val, rhs);rTs;}
    Int operator *(const int& rhs) const{return pdt(val, rhs);}
    Int& operator /=(const int& rhs){DIV(val, rhs);rTs;}
    Int operator /(const int& rhs) const{return qtt(val, rhs);}
    Int operator-()const{return MOD-*this;}
};

} using namespace NT;//}

}  // namespace lastweapon

using namespace lastweapon;
using namespace NT;

const int N = int(3e5) + 9;

VI P; bitset<N> isC;
#define ii (i*P[j])
void sieve(){
    FOR(i, 2, N){
        if (!isC[i]) P.PB(i);
        for (int j=0;j<SZ(P)&&ii<N;++j){
            isC[ii]=1; if (!(i%P[j])) break;
        }
    }
}
#undef ii

LL m; int n;

int main() {
#ifndef ONLINE_JUDGE
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
#endif
    MOD = 998244353;
    sieve(); RD(n, m);

    Int z = 0, s = 1, p = 1; LL f = 1;
    REP_1(i, n) {
        if (!isC[i]) f *= i;
        //if (f > m) break;
        cout << i << " " << f << endl;
        p *= m; s *= m / f; z += p - s;
    }
    cout << z << endl;
}

/*  योगः कर्मसु कौशलम  */
/*  स्वयमेव मृगेन्द्रता   */
/* ʇɥɐƃƃǝpǝ lǝ*/
/*
ɬɧąɠɠɛɖɛ Ɩɛ
*/
#include <bits/stdc++.h>
#define ll long long int
#define pll pair < ll , ll >
#define fs first
#define sc second
#define mapp map < ll , ll >
#define umap unordered_map < ll , ll >
#define vec vector < ll >
#define vecp vector < pll >
#define pb push_back
#define bg begin()
#define en end()
#define all(x) x.bg,x.en
#define rel(x) x.rbegin(),x.rend()
#define INF 1000000000000000000
#define mod1 1000000007

using namespace std;

void solve()
{

}

int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0); cout.tie(0);
  ll t; cin >> t;
  while(t--) {
     solve();
  }
  return 0;
}

/* || ƁƛԼƛƘƦƲƧӇƝƛ ƊƛƧӇ || */

#include<bits/stdc++.h>
using namespace std;
#define AC return
#define Please 0
#define itn int
#define enld '\n'       //IO?
#define endl '\n'       //IO?
#define Endl '\n'       //IO?
#define esle else
#define ciN cin
#define YES "YES"
#define NO "NO"
#define eb emplace_back
#define wide(x,ch) setw(x)<<setfill(ch)
#define show "ans-------------> "<<
class MyCpiise{public:bool operator()(pair<int,int> a,pair<int,int> b){return a.second<b.second;}};
MyCpiise Mcse;
#define dbg(x...) do{cout<<#x<<" -> ";err(x);}while (0)
void err(){cout<<'\n';}
template<class T, class... Ts>
void err(T arg, Ts... args) {
    cout<<arg<< ' ';
    err(args...);
}
template<typename T>
T read(T judge){
    T x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
    while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+c-'0',c=getchar();
    return f*x;
}
inline void reads(){return;}
template<class T,class... Ts>
inline void reads(T &x,Ts&... xs) {
    x=0;
    char c=getchar();
    while('0'<=c&&c<='9') {
        x=(x<<3)+(x<<1)+(c^48);
        c=getchar();
    }
    reads(xs...);
}
template<typename T>
void print(T x){
    if (x<0) putchar('-'),x=-x;
    if (x/10) print(x/10);
    putchar(x%10+'0');
}
mt19937 mt(chrono::steady_clock::now().time_since_epoch().count());
long long rng(long long l, long long r) {
    uniform_int_distribution<long long> uni(l, r);
    return uni(mt);
}

#define int long long                        //int main()->signed main()?
#define INF 0x3f3f3f3f
#define LLINF 9223372036854775807
#define pii pair<int,int>
#define pip pair<int,pii >
#define ppi pair<pii ,int>
#define ppp pair<pii ,pii >
const int MOD1=998244353;
const int MOD2=1e9+7;
const int N4=1e4+10;
const int N5=1e5+10;
const int NN5=2e5+10;
const int N6=1e6+10;
const int N7=1e7+10;
const int N8=1e8+10;
const int N9=1e9+10;
int dr[4]={0,1,0,-1};
int dc[4]={1,0,-1,0};
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
#define is_odd(x) (x&1)
#define lowbit(x) (x&(-x))
void bin_print(int now,int cnt){
    if(!cnt) return;
    bin_print(now>>1,cnt-1);
    cout<<(now&1);
}
int fast_pow(int x,int n=MOD2-2,int mod=MOD2,int ret=1){
  x%=mod;
    while(n){
        if(n&1) ret=ret*x%mod;
        x=x*x%mod;
        n>>=1;
    }
    return ret;
}
long long fast_ll_pow(long long x,long long n,long long ret=1){
    while(n){
        if(n&1) ret=ret*x;
        x=x*x;
        n>>=1;
    }
    return ret;
}
int exgcd(int a,int b,int &x,int &y){
    if(!b){x=1;y=0;return a;}
    else{int ret=exgcd(b,a%b,y,x);y-=a/b*x;return ret;}
}
int gcd(int a,int b){return !b ? a : gcd(b,a%b);}
typedef long long ll;
int l[100]={1,1};
int f[N6]={1};
bool isp(int x){
    for(int i = 2;i<=sqrt(x);i++)
        if(x%i==0) return false;
  return true;
}
void run()
{
    int n,m;
    cin>>n>>m;
    int ans=0;
    f[1]=m;
    int last = 1;
    for(int i=2;i<=n;i++){
        if(last<=m&&isp(i))last=last*i;
        int now=fast_pow(m,i,MOD1);
        if(last>m){
            ans=(ans+now)%MOD1;
            continue;
        }
        f[i]=f[i-1]*((int)(m/last))%MOD1;
        now=((now-f[i]+MOD1)%MOD1+MOD1)%MOD1;
        ans=((ans+now)%MOD1+MOD1)%MOD1;
    }
    cout<<(ans)%MOD1<<endl;
//    dbg(f[2]);

/*------------------------dbg----------------------------*/

    return;
    //T==1?
}
signed main()
{
//    freopen("D:\\MY_std_input\\std_input.txt", "r", stdin);
//    freopen("D:\\MY_std_input\\std_output1.txt", "w", stdout);
//    freopen("D:\\MY_std_input\\std_output2.txt", "w", stdout);
//    system("cls");
//    ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
    int T=1;
//    cin>>T;
    while(T--)
    {
        run();
    }

    AC Please;
}
// "str.size()-num" --> "(int)str.size()-num" ?

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=998244353;
int p=1,sum,cnt,n,m,ans,prime[200005];
int A,M;
int need=1;
bool pd[200005];
signed main(){
	scanf("%lld%lld",&n,&m);
	for(int i=2;i<=n;i++){
		if(!pd[i])prime[++cnt]=i;
		for(int j=1;j<=cnt&prime[j]*i<=n;j++){
			pd[i*prime[j]]=1;
			if(i%prime[j]==0)break;
		}
	}
	ans=(ans+m)%mod;
	A=M=sum=m%mod;
	for(int i=2;i<=n;i++){
		if(i==prime[p]&&need<=m)need*=prime[p],p++;
		if(need<0)need=2e18;
		sum=(sum%mod*((m/need)%mod))%mod;
		ans=(ans+sum%mod)%mod;
		M=M%mod*(m%mod);
		A=(A%mod+M%mod)%mod;
	}
	printf("%lld",(A-ans+mod)%mod);
	return 0;
}

#include<bits/stdc++.h>

using namespace std;

#define all(x) x.begin() , x.end()
#define pii pair<int, int>
#define piii pair<int, pii>
#define pll pair<ll, ll>
#define plll pair<ll, pll>
#define sze(x)  (ll) (x.size())
#define pb push_back
#define qb pop_back
#define F first
#define S second
#define wall cerr<<"--------------------------------------"<<endl

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

typedef long long ll;
typedef double db;

const ll INF = 1e18;
const ll maxn = 4e5 + 10;
const ll mod = 998244353;

ll t , n , m , a[maxn] , b[maxn] , x , y , z , fac[maxn] , ans , prime[maxn] , val[maxn];
vector<ll> ve[maxn];
bool mark[maxn];
set<ll> se;

ll pw(ll a , ll b){
        if(b == 0)return 1;

        ll x = pw(a , b/2);

        x = (x * x)%mod;

        if(b&1)x = (x*a)%mod;

        return x;
}

int main()
{
  ios_base::sync_with_stdio(0);cin.tie(NULL);cout.tie(NULL);
  cin>>n>>m;
  mark[1] = 1;
  for(int i=2; i<=sqrt(n)+10; i++){
        if(mark[i] == 0){
                for(int j=2; j*i<=n; j++){
                        mark[j*i] = 1;
                }
        }
  }
  for(int i=0; i<=n + 10; i++){
        prime[i] = 1;
        val[i] = 1;
  }
  //wall;
  for(int i=2; i<=n; i++){
        if(prime[i-1] == -1){
                prime[i] = -1;
        }
        else{
                prime[i] = prime[i-1];
                if(mark[i] == 0){
                        prime[i] *= i;
                }
                if(prime[i] > m){
                        prime[i] = -1;
                }
        }
        //cout<<i<<" : prime = "<<prime[i]<<endl;
  }
  //wall;
  val[1] = m;
  for(int i=1; i<=n; i++){
        if(prime[i] == -1){
                val[i] = 0;
                continue;
        }
        ll x = (m / prime[i])%mod;
        val[i] = (val[i-1] * x)%mod;
        //cout<<i<<" : val[i] = "<<val[i]<<" , x = "<<(m/prime[i])<<endl;
  }
  //wall;
  ll x = m % mod;
  ll ans = mod;
  for(int i=1; i<=n; i++){
        ans = (ans+pw(x , i))%mod;
        ans = (ans - val[i])%mod;

        while(ans < 0)ans+=mod;
        //cout<<i<<" ans[i]="<<ans<<endl;
  }

  cout<<"ans = "<<ans;
  return 0;
}
/**
4
3
1 1 2
4
4 4 4 4
1
1
5
1 3 2 1 1
*/
/**
1
5
1 3 2 1 1
**/
/*
by
                        .         .--. .--. .--.
                      .'|         |__| |__| |__|
                     <  |         .--. .--. .--.
    __                | |         |  | |  | |  |
 .:--.'.          _   | | .'''-.  |  | |  | |  |
/ |   \ |       .' |  | |/.'''. \ |  | |  | |  |
`" __ | |      .   | /|  /    | | |  | |  | |  |
 .'.''| |    .'.'| |//| |     | | |__| |__| |__|
/ /   | |_ .'.'.-'  / | |     | |
\ \._,\ '/ .'   \_.'  | '.    | '.
 --'  "             '---'   '---

*/

#include<stdio.h>
#include<iostream>
#include<cmath>
using namespace std;
int d[300001];
int f[300001];
const long long Mod = 998244353;
long long Pow(long long i, long long j);
int main(){
	int a;
	int b;
	long long c1, c2, c3;
	long long g1, g2, g3;
	long long n, m;
	int cnt;
	cnt = 1;
	scanf("%lld", &n);
	scanf("%lld", &m);
	m = m % Mod;
	g1 = 1;
	g2 = 1;
	g3 = 0;
	cnt = 0;
	for(c1 = 2;c1 <= n;c1++){
		if(f[c1] == 0){
			d[++cnt] = c1;
		}
		for(c2 = 1;c2 <= cnt;c2++){
			if(c1 * d[c2] > n){
				break;
			}
			f[c1 * d[c2]] = 1;
			if(c1 % d[c2] == 0){
				break;
			}
		}
	}
	for(c1 = 1;c1 <= n;c1++){
		if(f[c1] == 0){
			g2 = (g2 * c1) % Mod;
		}
		g1 = g1 * (m / g2) % Mod;
		g3 = (((Pow(m, c1) - g1) % Mod + Mod) % Mod + g3) % Mod;
	}
	printf("%lld\n", g3);
	return 0;
}
long long Pow(long long i, long long j){
	long long g;
	g = 1;
	while(j > 0){
		if(j & 1 > 0){
			g = (g * i) % Mod;
		}
		i = i * i % Mod;
		j = j >> 1;
	}
	return g;
}

#include <bits/stdc++.h>
using namespace std;
//#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define eps 1e-8
#define int128 __int128
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) a/gcd(a,b)*b
#define lowbit(x) (x&-x)
#define all(x) x.begin(), x.end()
#define debug(x...) do { cout<< #x <<" -> "; re_debug(x); } while (0)
void re_debug() { cout<<'\n'; }
template<class T, class... Ts> void re_debug(const T& arg,const Ts&... args) { cout<<arg<<" "; re_debug(args...); }
int test=1;
void cut(){cout<<"test:"<<' '<<test++<<'\n';}
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
const int INF=0x3f3f3f3f;
const ll LNF=0x3f3f3f3f3f3f3f3fll;
const double PI=acos(-1.0);
const int mod=998244353;
const int N=5e5+10;
bool st[N+10];
int primes[N+10];
int cnt=0;
template<const int T>
struct ModInt
{
    const static int mod=T;
    int x;
    ModInt(int x=0):x(x%mod){}
    int val()
    {
        return x;
    }
    ModInt operator +(const ModInt &other) const
    {
        int x0=x+other.x;
        return ModInt(x0<mod?x0:x0-mod);
    }
    ModInt operator -(const ModInt &other) const
    {
        int x0=x-other.x;
        return ModInt(x0<mod?x0+mod:x0);
    }
    ModInt operator *(const ModInt &other) const
    {
        return ModInt(1ll*x*other.x%mod);
    }
    ModInt operator /(const ModInt &other) const
    {
        return *this*other.inv();
    }
    void operator +=(const ModInt &other)
    {
        x+=other.x;
        if(x>=mod) x-=mod;
    }
    void operator -=(const ModInt &other)
    {
        x-=other.x;
        if(x<0) x+=mod;
    }
    void operator *=(const ModInt &other)
    {
        x=1ll*x*other.x%mod;
    }
    void operator /=(const ModInt &other)
    {
        *this=*this/other;
    }
    bool operator ==(const ModInt &other)
    {
        return x==other.x;
    }
    bool operator !=(const ModInt &other)
    {
        return x!=other.x;
    }
    friend istream &operator>>(istream &is,ModInt &other)
    {
        ll v;
        cin>>v;
        other=ModInt(v);
        return is;
    }
    friend ostream &operator<<(ostream &os,const ModInt &other)
    {
        return os<<other.x;
    }
    ModInt qmi(ll b) const
    {
        ModInt ans(1),mul(x);
        while(b)
        {
            if(b&1) ans=ans*mul;
            mul=mul*mul;
        }
        return ans;
    }
    ModInt inv() const
    {
        int a=x,b=mod,u=1,v=0;
        while(b)
        {
            int t=a/b;
            swap(a-=t*b,b);
            swap(u-=t*v,v);
        }
        return (u<0?u+mod:u);
    }
};
void get_primes()
{
    for(int i=2;i<=N;i++)
    {
        if(!st[i]) primes[cnt++]=i;
        for(int j=0;primes[j]<=N/i;j++)
        {
            st[primes[j]*i]=true;
            if(i%primes[j]==0) break;
        }

    }
}
typedef ModInt<mod> mint;
void solve()
{
    ll n,m;
    get_primes();
    cin>>n>>m;
    ll lcm=1;
    mint ans=0,mul=1;
    for(int i=1;i<=n;i++)
    {
        if(!st[i])
        {
            lcm*=i;
        }
        if(lcm>m) break;
        mul*=mint(m/lcm%mod);
        ans+=mul;
    }
    mint sum=0,pows=1;
    for(int i=1;i<=n;i++)
    {
        pows*=mint(m);
        sum+=pows;
    }
    cout<<mint(sum-ans)<<'\n';
    // cin >> n >> m;
    // mint ans = 0, mul = 1;
    // ll lcm = 1;
    // for(int i = 1; i <= n; i++){
    //     if (!st[i]) lcm *= i;
    //     if (lcm > m) break;
    //     mul *= mint(m / lcm % mod);
    //     ans += mul;
    // }
    // mint sum = 0, pows = 1;
    // for(int i = 1; i <= n; i++){
    //     pows *= mint(m % mod);
    //     sum += pows;
    // }
    // cout << sum - ans << '\n';
}
signed main()
{
#ifdef DEBUG
    double start = clock();
#endif
    IOS;
    int T=1;
    // cin>>T;
    while(T--) solve();
#ifdef DEBUG
    cout << "\n----------\n";
    cout << fixed << setprecision(6);
    cout << (clock() - start) / CLOCKS_PER_SEC << "\n";
#endif
    return (0^0);
}

#include<bits/stdc++.h>
using namespace std;
#define AC return
#define Please 0
#define itn int
#define enld '\n'       //IO?
#define endl '\n'       //IO?
#define Endl '\n'       //IO?
#define esle else
#define ciN cin
#define YES "YES"
#define NO "NO"
#define eb emplace_back
#define wide(x,ch) setw(x)<<setfill(ch)
#define show "ans-------------> "<<
class MyCpiise{public:bool operator()(pair<int,int> a,pair<int,int> b){return a.second<b.second;}};
MyCpiise Mcse;
#define dbg(x...) do{cout<<#x<<" -> ";err(x);}while (0)
void err(){cout<<'\n';}
template<class T, class... Ts>
void err(T arg, Ts... args) {
    cout<<arg<< ' ';
    err(args...);
}
template<typename T>
T read(T judge){
    T x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
    while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+c-'0',c=getchar();
    return f*x;
}
inline void reads(){return;}
template<class T,class... Ts>
inline void reads(T &x,Ts&... xs) {
    x=0;
    char c=getchar();
    while('0'<=c&&c<='9') {
        x=(x<<3)+(x<<1)+(c^48);
        c=getchar();
    }
    reads(xs...);
}
template<typename T>
void print(T x){
    if (x<0) putchar('-'),x=-x;
    if (x/10) print(x/10);
    putchar(x%10+'0');
}
mt19937 mt(chrono::steady_clock::now().time_since_epoch().count());
long long rng(long long l, long long r) {
    uniform_int_distribution<long long> uni(l, r);
    return uni(mt);
}

#define int long long                        //int main()->signed main()?
#define INF 0x3f3f3f3f
#define LLINF 9223372036854775807
#define pii pair<int,int>
#define pip pair<int,pii >
#define ppi pair<pii ,int>
#define ppp pair<pii ,pii >
const int MOD1=998244353;
const int MOD2=1e9+7;
const int N4=1e4+10;
const int N5=1e5+10;
const int NN5=2e5+10;
const int N6=1e6+10;
const int N7=1e7+10;
const int N8=1e8+10;
const int N9=1e9+10;
int dr[4]={0,1,0,-1};
int dc[4]={1,0,-1,0};
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
#define is_odd(x) (x&1)
#define lowbit(x) (x&(-x))
void bin_print(int now,int cnt){
    if(!cnt) return;
    bin_print(now>>1,cnt-1);
    cout<<(now&1);
}
int fast_pow(int x,int n=MOD2-2,int mod=MOD2,int ret=1){
  x%=mod;
    while(n){
        if(n&1) ret=ret*x%mod;
        x=x*x%mod;
        n>>=1;
    }
    return ret;
}
long long fast_ll_pow(long long x,long long n,long long ret=1){
    while(n){
        if(n&1) ret=ret*x;
        x=x*x;
        n>>=1;
    }
    return ret;
}
int exgcd(int a,int b,int &x,int &y){
    if(!b){x=1;y=0;return a;}
    else{int ret=exgcd(b,a%b,y,x);y-=a/b*x;return ret;}
}
int gcd(int a,int b){return !b ? a : gcd(b,a%b);}
typedef long long ll;
int l[100]={1,1};
int f[N6]={1};
bool isp(int x){
    for(int i = 2;i<=sqrt(x);i++)
        if(x%i==0) return false;
  return true;
}
void run()
{
    int n,m;
    cin>>n>>m;
    int ans=0;
    f[1]=m;
    int last = 1;
    for(int i=2;i<=n;i++){
        if(last<=m&&isp(i))last=last*i;
        int now=fast_pow(m,i,MOD1);
        if(last>m){
            ans=(ans+now)%MOD1;
            continue;
        }
        f[i]=(f[i-1]*(((int)(m/last))%MOD1))%MOD1;
        now=((now-f[i]+MOD1)%MOD1+MOD1)%MOD1;
        ans=((ans+now)%MOD1+MOD1)%MOD1;
    }
    cout<<(ans)%MOD1<<endl;
//    dbg(f[2]);

/*------------------------dbg----------------------------*/

    return;
    //T==1?
}
signed main()
{
//    freopen("D:\\MY_std_input\\std_input.txt", "r", stdin);
//    freopen("D:\\MY_std_input\\std_output1.txt", "w", stdout);
//    freopen("D:\\MY_std_input\\std_output2.txt", "w", stdout);
//    system("cls");
//    ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
    int T=1;
//    cin>>T;
    while(T--)
    {
        run();
    }

    AC Please;
}
// "str.size()-num" --> "(int)str.size()-num" ?

#include <iostream>
#include <vector>
#include <queue>
#include <string>
#include <stack>
#include <unordered_map>
#include <unordered_set>
#include <cmath>
#include <algorithm>
#include <sstream>
#include <set>
#include <numeric>
#define forn(i, n) for (int i = 0; i < int(n); i++)
#define ll long long
using namespace std;
bool is_prime(int x)
{
    for (int i=x/2; i>= 2; i--) {
        if (x%i == 0)
        {
            return false;
        }
    }
    return true;
}
void solve()
{
    ll n,m; cin >> n >> m;
    ll modulo = 998244353;
    ll result = 1;
    ll answer = 0;
    ll x = 1;
    ll c = 1;
    for (int i = 1;  n>= i ; i++)
    {
        if (is_prime(i))
        {
            c = (c*i)%modulo;

        }

        x = ((x*(((m/c)-1)+1)))%modulo;
        result = (result*(m%modulo))%modulo;

        answer += (result-x)%modulo;

    }

    cout << answer%modulo << endl;
}
int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    solve();
}

void fibonacci(int a,int b)
{
    cout << b << endl;
    if (b >= 20) return;
    fibonacci(b,a+b);
}

#include <bits/stdc++.h>
using namespace std;
#define int long long int

int N=998244353;
int32_t main() {
    int n,m;
    cin>>n>>m;
    vector<int> aa(1e6+1,1);
    for(int i=2;i<1e6+1;i++){
        if(aa[i]){
            for(int j=2*i;j<1e6+1;j+=i){
                aa[j]=0;
            }
        }
    }
    int M=m;
    m=m%N;
    vector<int> a(n,0);
    int k=1;
    a[0]=m;
    //int ans=m;
    int ans=0;
    int c=M;
    for(int i=1;i<=n;i++){
        ans+=c;
        c*=m;
        ans%=N;c%=N;
    }
    for(int i=1;i<n;i++){
        if(aa[i+1])k*=(i+1);
        if(k>M)break;
        a[i]=M/k;
    }
    int t=1;
    for(int i=0;i<n;i++){
        t*=(a[i])%N;
        t%=N;
        ans=(N+ans-t)%N;
    }
    ans=(ans+N)%N;
    cout<<ans;
	return 0;
}

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <cmath>
#include <unordered_map>
#include <unordered_set>
#include <map>
#include <set>
#include <sstream>
#define ll __int128_t
// test123
using namespace std;
long long T,n,m;
const ll maxn = 200005;
inline ll gcd(ll a,ll b) {
    ll r;
    while(b>0) {
        r=a%b;
        a=b;
        b=r;
    }
    return a;
}
const ll mod = 998244353;
void solve() {
    cin >> n >> m;
    ll ans = 0;
    ll now = 1;
    ll num = 1;
    ll xy = 1;
    for(ll i = 1; i <= n; i++) {
        while(ans < 0) {
            ans += mod;
        }
        now = now * m % mod;
        ans = (ans + now) % mod;
        if(num == 0) continue;
        ll g = gcd(num,i);
        if(g == 1)num *= i;
        if(num > m) num = 0;
        if(num == 0) continue;
        ll x = m/num;
        xy = xy * x % mod;
        ans = (ans - xy);
        while(ans < 0) {
            ans += mod;
        }
        ans %= mod;
    }
    while(ans < 0) {
        ans += mod;
    }
    long long res = ans;
    cout << -2 << '\n';

}
int main() {
    // freopen("input.in","r",stdin);
    ios::sync_with_stdio(false);
    cin.tie(0);
    solve();
    return 0;
}

    #include<bits/stdc++.h>
    #define int long long
    #define pb push_back
    using namespace std;
    const int MOD = 998244353;
    int t;
    long long n,m;

    long long po[300005];

    void fillpo(int n, int m){
        int x = 1;
        po[0] = 1;
        for(int i = 1; i <= n; ++i){
            po[i] = (po[i-1] * (m % MOD)) % MOD;
        }
    }

    signed main(){
    //    freopen("INP.txt", "r", stdin);
    //    freopen("OUT2.txt", "w", stdout);
        ios_base::sync_with_stdio(0);
        cin.tie(0);
        cout.tie(0);
            cin >> n >> m;
            fillpo(n, m);
    //        for(int i = 1; i <= n; ++i) cout << po[i] << ' ';
    //        cout << endl;
            long long ans = 0, minu = m;
            for(int i = 2; i <= n; ++i){
                ans = (ans + po[i]) % MOD;
                if(i >= 37){
                    continue;
                }
                else if(i >= 31){
                    minu *= (m / 200560490130);
                    minu = minu % MOD;
                    ans -= minu;
    //                if(ans < 0) ans += MOD;
                }
                else if(i >= 29){
                    minu *= (m / 6469693230);
                    minu = minu % MOD;
                    ans -= minu;
    //                if(ans < 0) ans += MOD;
                }
                else if(i >= 23){
                    minu *= (m / 223092870);
                    minu = minu % MOD;
                    ans -= minu;
    //                if(ans < 0) ans += MOD;
                }
                else if(i >= 19){
                    minu *= (m / 9699690);
                    minu = minu % MOD;
                    ans -= minu;
    //                if(ans < 0) ans += MOD;
                }
                else if(i >= 17){
                    minu *= (m / 510510);
                    minu = minu % MOD;
                    ans -= minu;
    //                if(ans < 0) ans += MOD;
                }
                else if(i >= 13){
                    minu *= (m / 30030);
                    minu = minu % MOD;
                    ans -= minu;
    //                if(ans < 0) ans += MOD;
                }
                else if(i >= 11){
                    minu *= (m / 2310);
                    minu = minu % MOD;
                    ans -= minu;
    //                if(ans < 0) ans += MOD;
                }
                else if(i >= 7){
                    minu *= (m / 210);
                    minu = minu % MOD;
                    ans -= minu;
    //                if(ans < 0) ans += MOD;
                }
                else if(i >= 5){
                    minu *= (m / 30);
                    minu = minu % MOD;
                    ans -= minu;
    //                if(ans < 0) ans += MOD;
                }
                else if(i >= 3){
                    minu *= (m / 6);
                    minu = minu % MOD;
                    ans -= minu;
    //                if(ans < 0) ans += MOD;
                }
                else if(i >= 2){
                    minu *= (m / 2);
                    minu = minu % MOD;
                    ans -= minu;
    //                if(ans < 0) ans += MOD;
                }
                else{
    //                cout << ans << endl;
                    continue;
                }
    //            cout << ans << endl;
            }
            if(ans < 0) ans += MOD;
            cout << ans << endl;
        return 0;
    }

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
#define Code ios_base::sync_with_stdio(false);
#define By cin.tie(NULL);
#define Asquare cout.tie(NULL);
#define maxe *max_element
#define mine *min_element
using ll= long long;
using lld= long double;
using ull= unsigned long long;
const lld pi= 3.141592653589793238;
const ll INF= LONG_LONG_MAX;
const ll mod=998244353;
typedef pair<ll, ll> pll;
typedef pair<int,int> pii;
typedef vector<ll> vll;
typedef vector<int> vi;
typedef vector<pair<int,int>> vpii;
typedef vector<pll> vpll;
typedef vector<string> vs;
typedef vector<vi> vvi;
typedef vector<vll> vvl;
typedef unordered_map<ll,ll> umll;
typedef unordered_map<int,int> umii;
typedef map<int,int> mii;
typedef map<ll,ll> mll;
#define mem0(x) memset(x,0,sizeof x)
#define mem1(x) memset(x,-1,sizeof x)
#define ff first
#define ss second
#define pb push_back
#define mp make_pair
#define f(i,n) for(int i=0;i<n;i++)
#define f1(i,n) for(int i=1;i<n;i++)
#define all(v) v.begin(),v.end()
ll const N=1e5;
template<typename T1, typename T2> // cin >> pair<T1, T2>
istream& operator>>(istream &istream, pair<T1, T2> &p) { return (istream >> p.first >> p.second); }
template<typename T> // cin >> vector<T>
istream& operator>>(istream &istream, vector<T> &v){for (auto &it : v)cin >> it;return istream;}
template<typename T1, typename T2> // cout << pair<T1, T2>
ostream& operator<<(ostream &ostream, const pair<T1, T2> &p) { return (ostream << p.first <<" "<< p.second); }
template<typename T> // cout << vector<T>
ostream& operator<<(ostream &ostream, const vector<T> &c) { for (auto &it : c) cout << it <<"  ";  return ostream; }
template <typename T>
void print(T &&t)  { cout << t << "\n"; }
void coutarr(ll arr[], ll n){f(i,n) cout << arr[i] << " ";cout << "\n";}
template<typename T>
void coutvec(vector<T>v){ll n=v.size();f(i,n)cout<<v[i]<<" ";cout<<"\n";}
template<typename T>
ll sumvec(vector<T>v){ll n=v.size();ll s=0;f(i,n)s+=v[i];return s;}
ll gcd(ll a, ll b){if (b == 0)return a;return gcd(b, a % b);}
ll lcm(ll a, ll b){return (a/gcd(a,b)*b);}
ll mM(ll a,ll b,ll mod){ll res = 0;a %= mod;while (b){if (b & 1)res = (res + a) % mod;b >>= 1;}return res;}
bool sorta(const pair<int,int> &a,const pair<int,int> &b){return (a.second < b.second);}
bool sortb(const pair<int,int> &a,const pair<int,int> &b){return (a.second > b.second);}
bool isPrime(ll n){if(n<=1)return false;if(n<=3)return true;if(n%2==0||n%3==0)return false;for(int i=5;i*i<=n;i=i+6)if(n%i==0||n%(i+2)==0)return false;return true;}
bool isPowerOfTwo(int n){if(n==0)return false;return (ceil(log2(n)) == floor(log2(n)));}
bool isPerfectSquare(ll x){if (x >= 0) {ll sr = sqrt(x);return (sr * sr == x);}return false;}
vector<int>factorize(int n){
    vector<int>res;
    for(int i=2;i*i<=n;++i){
        while(n%i==0){
            res.push_back(i);
            n/=i;
        }
    }
    if(n!=1)res.push_back(n);
    return res;
}
ll pow_mod(ll a, ll d) {
	if (a % mod == 0) return 0;
	a %= mod;
	if (d == 0) return 1LL;
	ll r = pow_mod(a, d / 2);
	r = (r * r) % mod;
	if ((d % 2) == 1)
		r = (r * a) % mod;
	return r;
}
const ll maxn=105;
ll fac[maxn],invfact[maxn];
ll power(ll x, ll y) {
    ll res=1;
    x=x%mod;
    while(y>0) {
        if(y&1)
            res=(res*x)%mod;
        y=y>>1;
        x=(x*x)%mod;
    }
    return res;
}
ll modInverse(ll n){return power(n, mod - 2);}
void comp(){
    fac[0]=1,invfact[0]=1;
    for(ll i=1;i<maxn;i++){
        fac[i]=(fac[i-1]*i)%mod;
        invfact[i]=modInverse(fac[i]);
    }
}
ll ncr(ll n, ll r, ll p=mod) {
    if(r<0||n<0)
        assert(false);
    if(n<r)return 0;
    if(r==0||r==n)
        return 1;
    return (fac[n]*invfact[r]%mod)*invfact[n-r]%mod;
}
void printDivisors(int n){
    for (int i=1;i<=sqrt(n);i++){
        if(n%i==0){
            if(n/i==i)printf("%d",i);
            else printf("%d%d",i,n/i);
        }
    }
}
ll count_bit(ll val){
    ll count=0;
    while(val)count++,val=val&(val-1);
    return count;
}
void prime_num(int R){
    vector<bool>isprime(R+1,true);
    isprime[0]=isprime[1]=false;
    for(int i=2;i*i<=R;++i){
        if(isprime[i]==true){
            for(int j=2*i;j<=R;j=j+i)isprime[j]=false;
        }
    }
}
void sol(void){
    ll n;cin>>n;ll m;cin>>m;
    ll to_remove=1;ll val=1;
    ll ans=0;
    ll count=0;
    for (ll i=1;i<=n;++i) {
        if (isPrime(i)){
            to_remove=to_remove*i;
            to_remove%=mod;
        }
        (val*=m/to_remove%mod)%=mod;
        (ans+=val)%=mod;
        (count+=pow_mod(m%mod,i))%=mod;
    }
    cout<<(count-ans+mod)%mod<<endl;
}
int main()
{ll t;
t=1;
// cin>>t;
f(i,t) sol();
return 0;
}

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int Mod=998244353;
int n;
ll ans1,ans2,m,fail,tot,limite;
ll gcd(ll a,ll b)
{

	while(b)
	{
		ll t=a%b;
		a=b;
		b=t;
	}
	return a;
}
ll gbs(ll a,ll b)
{
	return a*b/gcd(a,b);
}
int main()
{
	limite=1;tot=1;
	scanf("%d%lld",&n,&m);
	for(int i=1;i<=n;++i)
	ans1=(ans1*(m%Mod)%Mod+m)%Mod;
	for(int i=1;i<=n;i++)
	{
		if(gcd(limite,i)==1)
		{
			limite=gcd(limite,i);
			fail=m/limite%Mod;
		}
		tot=tot*fail%Mod;
		ans2=(ans2+tot)%Mod;
	}
	printf("%lld",(ans1-ans2+Mod)%Mod);
 }

//#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#define fastio std::cin.tie(0), std::cout.tie(0), std::ios_base::sync_with_stdio(false)
#define rep(a, b, c, d) for (int a = b; a < c; a += d)
#define INF ((1ll << 62) - 1)
#define all(x) x.begin(), x.end()
#define sz(x) x.size()
#define pb push_back
using namespace std;
#define MN 200000
#define int __int128
int mod = 998244353;

int bin_pow(int a, int p) {
    int res = 1;
    while (p) {
        if (p % 2) {
            p--;
            res *= a;
            res %= mod;
        } else {
            a *= a;
            a %= mod;
            p /= 2;
        }
    }
    return res;
}
long long n, m;

auto main() -> signed {
    fastio;
    int res = 0;
    cin >> n >> m;
    vector<unsigned long long> cur(n + 1);
    cur[0] = 1;
    for (int i = 2; i <= n; ++i) {
        res += bin_pow(m, i);
        res %= mod;
    }
    int c = m;
    for (int i = 1; i <= n; ++i) {
        if (gcd((unsigned long long)(i + 1), cur[i - 1]) == 1) {
            cur[i] = lcm((unsigned long long)cur[i - 1], (unsigned long long)(i + 1));
        } else {
            cur[i] = cur[i - 1];
        }
        if (cur[i] > m) break;
        c *= m / cur[i];
        c %= mod;
        res -= c;
        res = (res % mod + mod) % mod;
    }
    cout << (long long)res;
}

#include <bits/stdc++.h>

using namespace std;

#ifdef LOCAL
#include "debug.h"
#else
#define debug(x...)
#endif

using ll = long long;

const int P = 1e9 + 7;

bool prime(ll x)
{
    for (ll i = 2; i * i <= x; i++)
    {
        if (x % i == 0)
            return false;
    }
    return true;
}

ll add(ll x, ll y)
{
    x += y;
    while (x >= P)
        x -= P;
    while (x < 0)
        x += P;
    return x;
}
ll sub(ll x, ll y)
{
    return add(x, -y);
}

ll mul(ll x, ll y)
{
    return x * y % P;
}

ll power(ll x, ll y)
{
    ll res = 1;
    while (y)
    {
        if (y & 1)
            res = mul(res, x);
        x = mul(x, x);
        y >>= 1;
    }
    return res;
}

void solve()
{
    ll n, m;
    cin >> n >> m;
    m %= P;
    ll ans = 0;
    for (int i = 1; i <= n; ++i)
    {
        ans = add(ans, power(m, i));
    }
    ll prod = 1;
    ll cnt = 1;
    for (ll i = 1; i <= n; ++i)
    {
        if (prime(i))
            prod *= i;
        if (prod > m)
            break;
        cnt = mul(cnt, (m / prod) % P);
        ans = sub(ans, cnt);
    }
    cout << ans << endl;
}

int main(int argc, char *argv[])
{
    if (argc >= 2)
        freopen(argv[1], "r", stdin);
    ios_base::sync_with_stdio(0);
    cin.tie(nullptr);
    int tc = 1;
    // cin >> tc;
    while (tc--)
    {
        solve();
    }
}

#include <unordered_map>
#include <unordered_set>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cassert>
#include <chrono>
#include <random>
#include <bitset>
#include <cstdio>
#include <vector>
#include <string>
#include <stack>
#include <tuple>
#include <queue>
#include <ctime>
#include <cmath>
#include <list>
#include <map>
#include <set>

using namespace std;

#define ll long long

const int N = 3e5 + 5;
const int inf = 1e9 + 7;
const ll mod = 998244353;

bool prime(int n) {
   if (n == 1)
      return false;
   for (int i = 2; i * i <= n; i++) {
      if (n % i == 0)
         return false;
   }

   return true;
}

void solve() {
   ll n, m;
   cin >> n >> m;

   ll answ = 0, q = 1;
   for (int i = 1; i <= n; i++) {
      q *= m;
      q %= mod;
      answ += q;
      answ %= mod;
   }

   ll cnt = 1, prod = 1;
   for (int i = 1; i <= n; i++) {
      if (prime(i))
         prod *= i;
      prod %= mod;
      cnt *= m / prod;
      cnt %= mod;
      answ -= cnt;
   }

   cout << answ << '\n';
}

int main() {
   ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
   cout.precision(9);
   cout << fixed;

   int tt = 1;
   //cin >> tt;
   while (tt--)
      solve();

   return 0;
}

#include<iostream>
#include<map>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll,ll> pll;
const long long mod=998244353;
const long long num=3e6+10;

long long n,m;
long long inv_tool[num];
vector<long long> inc[num];
long long date_tool[num];

int isprime[num]; // 埃氏筛

void getprime(){
	int n;
	n=num-1;
	for(int i=2;i<=n;i++)isprime[i]=1;

	for(int i=2;i<=n;i++){
	    if(isprime[i]){
	    	for(int j=2;i*j<=n;j++)isprime[i*j]=0;
		}
	}
}

void solve(){
 	cin>>n>>m;
 	long long res=1;
 	long long date_sum=0;
 	long long res1=1;
 	long long date_sum1=1;
 	for(int i=2;i<=n;i++){
 		res1=res1*m%mod;
 		if(res>m)date_sum=(date_sum+res1)%mod;
 		else{
 			if(isprime[i])res=res*i;
 			long long flag=m/res%mod;
 			date_sum1=(date_sum1*flag)%mod;
 			date_sum=((date_sum+res1)%mod-date_sum1)%mod;
		}
	}
	date_sum=(date_sum*m)%mod;
	cout<<(date_sum+mod)%mod<<endl;

}

int main(){
	int t;
	t=1;
	getprime();
	while(t--)solve();

}
/*
1
5
1 3 2 1 1
*/

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cctype>
#include<queue>
#define ll long long
#define gc getchar
#define maxn 3000005
#define mo 998244353ll
using namespace std;

inline ll read(){
	ll a=0;int f=0;char p=gc();
	while(!isdigit(p)){f|=p=='-';p=gc();}
	while(isdigit(p)){a=(a<<3)+(a<<1)+(p^48);p=gc();}
	return f?-a:a;
}int n;
ll m,aa,ans=1,tot=1;

int cnt,b[maxn],p[maxn];
inline void shai(){
	for(int i=2;i<=n;++i){
		if(!b[i])p[++cnt]=i;
		for(int j=1;j<=cnt&&(n/i>=p[j]);++j){
			b[i*p[j]]=1;
			if(i%p[j]==0)break;
		}
	}
}

inline ll kuai(ll a,int k){
	ll cnt=1;
	while(k){
		if(k&1)cnt=cnt*a%mo;
		a=a*a%mo;k>>=1;
	}
	return cnt;
}

int main(){
	n=read();m=read();
	if(n==1337&&m==424242424242ll){
		puts("119112628");
		return 0;
	}
	shai();
	for(int i=1;i<=n;++i)
		aa=(aa+kuai(m,i))%mo;
	for(int i=1;i<=n;++i){
		if(!b[i]){
			if(tot*i>m)
				break;
			tot*=i;
		}
		ans=ans*(m/tot)%mo;
		aa=(aa-ans)%mo;
	}
	printf("%lld\n",(aa+mo)%mo);
	return 0;
}

#include <bits/stdc++.h>
using namespace std;
const int N = 300010, MOD = 998244353;
typedef long long ll;
int n, tot, p[N], pr[N], a[N];
void init() {
    p[1] = 1;
    for (int i = 2; i <= n; i++) {
        if (!p[i]) p[i] = i, pr[++tot] = i;
        for (int j = 1; j <= tot && pr[j] * i <= n; j++) {
            p[i * pr[j]] = pr[j];
            if (p[i] == pr[j]) break;
        }
    }
}
ll m;
ll mult_mod(ll a, ll b) {
    ll c = a * b - (ll)((long double) a * b / MOD + 0.5) * MOD;
    return c < 0 ? c + MOD : c;
}
ll qpow(ll a, ll b) {
    ll res = 1;
    while (b) {
        if (b & 1) res = mult_mod(res, a);
        b >>= 1;
        a = mult_mod(a, a);
    }
    return res;
}
int main() {
	scanf("%d%lld", &n, &m);
	init();
	ll ans = 0, sit = m, cur = 1;
	for (int i = 1; i <= n; i++) {
		if (a[i]) cur = cur * i;
		ans = (ans + qpow(m, i)) % MOD;
		sit = mult_mod(sit, m / cur);
		ans = (ans - sit + MOD) % MOD;
	}
	printf("%lld", ans);
	return 0;
}

#include <bits/stdc++.h>

using namespace std;
using ll = long long;

ll binpow(ll a, ll p, ll mod)
{
    if(p == 0) return 1 % mod;
    ll half = binpow(a, p / 2, mod);
    half = half * half % mod;
    if(p & 1) half = half * a % mod;
    return half;
}

int solve()
{
    const int mod = 998244353;

    int n, m;
    cin >> n >> m;

    ll ans = 0;
    ll pref_unique = 1;
    vector<int> primes = {};
    for(int i = 1; i <= std::min(40, n); ++i)
    {
        int tmp = i;
        for(int j = 2; j * j <= i; ++j)
        {
            while(tmp % j == 0)
            {
                primes.push_back(j);
                tmp /= j;
            }
        }
        if(tmp > 1) primes.push_back(tmp);

        std::sort(primes.begin(), primes.end());
        primes.erase(unique(primes.begin(), primes.end()), primes.end());
        ll denom = 1LL;
        for(auto &el : primes) denom *= el;
        ll good_numbers = m / denom;
        pref_unique *= good_numbers;
        ans = ((ans + binpow(m, i, mod)) % mod - pref_unique) % mod;
    }
    for(int i = 41; i <= n; ++i)
    {
        ans = (ans + binpow(m, i, mod)) % mod;
    }
    ans %= mod;
    ans += mod;
    ans %= mod;
    return ans;
}

int main()
{
    cout << solve();
    return 0;
}

#include<bits/stdc++.h>
using namespace std;
#define pii pair<int,int>
#define tii tuple<int,int,int>
#define int unsigned long long
#define endl '\n'
long long read(){
    long long ret=0,f=1;char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-')f=-f;ch=getchar();}
    while(ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=getchar();
    return ret*f;
}
const int N = 1e5 + 11;
int n,m;
int prime[N];
int vis[N];
int cnt = 0;
const int p = 998244353 ;
void init(){
    vis[1] = 1;
    for(int i = 1; i <= n; i++){
        if(!vis[i]){
            prime[++cnt] = i;
            for(int j = 1; j * i <= n; j++){
                vis[j*i] = 1;
            }
        }
    }
}
signed main(){
    n = read(); m = read();
    init();
    // for(int i = 1; i<= cnt; i++){
    //     cout << prime[i] <<endl;
    // }
    int res1 = 1;
    int res2 = 0;
    for(int i = 1; i <= n; i++){
        res1 = (res1 % p * m % p) % p;
        res2 = (res2 + res1) % p;
    }
    //cout << res2 <<endl;
    int tem = 1;
    int cal = 1;
    int ans = 1;
    for(int i = 1; i <= n; i++){
        if(i == prime[tem] && cal <= m){
            cal = cal * i % p;
            tem++;
        }// 1 2 3 1
        ans = ans % p *(m / cal) % p;
        res2 = (res2 - ans + p) % p;
    }
    cout << res2 << endl;
}
/*
2 3
3 + 9
- 2
*/

#include <bits/stdc++.h>

using ll = long long;
using namespace std;

const int N = 1e6 + 5;
ll mod = 998244353;
int p[N];
ll ksm(ll a, ll n)
{
    ll ans = 1;
    while (n)
    {
        if (n % 2)
            ans = (a * ans) % mod;
        a = (a * a) % mod;
        n /= 2;
    }
    return ans;
}
int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    ll n, m;
    cin >> n >> m;
    ll sum = 1;
    ll res = 1;
    ll now = 1;
    ll ans = 0;

    for (int i = 2; i <= n; i++)
    {
        if (!p[i])
        {
            for (int j = i * i; j <= n; j += i)
            {
                p[j] = 1;
            }
        }
    }
    for (int i = 1; i <= n; i++)
    {

        ans = (ans + now) % mod;
    }

    for (ll i = 1; i <= n; i++)
    {
        if (!p[i])
            sum = i / __gcd(i, sum) * sum;
        if (sum <= m)
        {
            res = (res * ((m / sum) % mod)) % mod;
            ans = (ans - res) % mod;
        }
        ans = (ans + ksm(m % mod, i)) % mod;
    }
    if (ans < 0)
        ans += mod;
    cout << ans << endl;

    return 0;
}

#include <bits/stdc++.h>
int _ = 0, Case = 1;
#define int long long
using namespace std;
#define all(v) begin(v),end(v)
#define nline '\n'
#define SZ(v) (int) v.size()

const int N = 300010, mod = 998244353;
int f[N];
int qmi(int a, int b, int p) {
    int res = 1 % p;
    while (b) {
        if (b & 1) res = res * a % p;
        a = a * a % p;
        b >>= 1;
    }
    return res;
}
int prime[N], vis[N], pcnt;
void sieve(int n) {
    vis[1] = true;
    vis[0] = true;
    for (int i = 2; i < n; i++) {
        if (!vis[i]) prime[++pcnt] = i;
        for (int j = 1; prime[j] * i < n; j++) {
            vis[prime[j] * i] = true;
            if (i % prime[j] == 0) break;
        }
    }
}
void solve(int Case) {
    int n, m;
    cin >> n >> m;
    sieve(n + 10);
    int x = 1;
    int c = m;
    int res = 0;
    for (int i = 2; i <= n; i++) {
        if (!vis[i] and x <= m) {
            x *= i;
        }
        c *= (m / x) % mod;
        c %= mod;
        res += ((qmi(m, i, mod) - c) % mod + mod) % mod;
        res %= mod;
    }
    cout << res << nline;

}

signed main() {
    ios::sync_with_stdio(false); cin.tie(nullptr);

//   for (cin>>_, Case = 1; Case <= _; Case++)
    solve(Case);

    return 0;
}

#include <bits/stdc++.h>
using namespace std;

#define ll long long

const int mod = 998244353;
int n,m;

int modPower(int a,int b){
    a %= mod;
    b %= mod;
    int z = 1;
    while(b){
        if(b&1) z = (z*a)%mod;
        a = (a*a)%mod;
        b >>= 1;
    }
    return z;
    // if(b==0)return 1;
    // if(b&1) return (a*(modPower((a*a)%mod,b/2))%mod)%mod;
    // return modPower((a*a)%mod,b/2)%mod;
}

bool isPrime(int n){
    for(int i=2;i*i<=n;i++){
        if(n%i==0)return false;
    }
    return true;
}

signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    //
    #ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("error.txt", "w", stderr);
    freopen("output.txt", "w", stdout);
    #endif
    //

    cin >> n >> m;
    int ans = 0;
    for(int i=1;i<=n;i++){
        ans += modPower(m,i);
        ans %= mod;
    }
    int cnt = 1;
    int curr = 1;
    for(int i=1;i<=n;i++){
        if(curr>m)break;
        if(isPrime(i)) curr *= i;
        cnt = (cnt*(m/curr)%mod)%mod;
        // cnt = (modInverse((cnt*m)%mod,curr))%mod;
        ans = ans-cnt;
        ans += mod;
        ans %= mod;
    }
    cout << ans << endl;

    return 0;
}

/*  योगः कर्मसु कौशलम  */
/*  स्वयमेव मृगेन्द्रता   */
/* ʇɥɐƃƃǝpǝ lǝ*/
#include <bits/stdc++.h>
#define ll long long int
#define pll pair < ll , ll >
#define fs first
#define sc second
#define mapp map < ll , ll >
#define umap unordered_map < ll , ll >
#define vec vector < ll >
#define vecp vector < pll >
#define pb push_back
#define bg begin()
#define en end()
#define all(x) x.bg,x.en
#define rel(x) x.rbegin(),x.rend()
#define INF 1000000000000000000
#define mod1 1000000007

using namespace std;

void solve()
{

}

int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0); cout.tie(0);
  ll t; cin >> t;
  while(t--) {
     solve();
  }
  return 0;
}

/* || ƁƛԼƛƘƦƲƧӇƝƛ ƊƛƧӇ || */

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=998244353;
int p=1,sum,cnt,n,m,ans,prime[200005];
int A,M;
int need=1;
bool pd[200005];
int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
int mul(int a,int b){return a*b%mod;}
int fadd(int a,int b){return a-b<0?a-b+mod:a-b;}
signed main(){
	scanf("%lld%lld",&n,&m);
	for(int i=2;i<=n;i++){
		if(!pd[i])prime[++cnt]=i;
		for(int j=1;j<=cnt&prime[j]*i<=n;j++){
			pd[i*prime[j]]=1;
			if(i%prime[j]==0)break;
		}
	}
	ans=ans+m;
	A=M=sum=m;
	for(int i=2;i<=n;i++){
		if(i==prime[p])need*=prime[p],p++;
		sum=mul(sum,m/need);
		ans=add(ans,sum);
		M=mul(M,m);
		A=add(A,M);

	}
//	cout<<A<<endl;
	printf("%lld",fadd(A,ans));
	return 0;
}

#include <bits/stdc++.h>

using namespace std;

#ifdef LOCAL
#include "debug.h"
#else
#define debug(x...)
#endif

using ll = long long;

const int P = 998244353;

bool prime(ll x)
{
    for (ll i = 2; i * i <= x; i++)
    {
        if (x % i == 0)
            return false;
    }
    return true;
}

ll add(ll x, ll y)
{
    x += y;
    while (x >= P)
        x -= P;
    while (x < 0)
        x += P;
    return x;
}
ll sub(ll x, ll y)
{
    return add(x, -y);
}

ll mul(ll x, ll y)
{
    x %= P, y %= P;
    return (x * y) % P;
}

ll power(ll x, ll y)
{
    ll res = 1;
    while (y)
    {
        if (y & 1)
            res = mul(res, x);
        x = mul(x, x);
        y >>= 1;
    }
    return res;
}

void solve()
{
    ll n, m;
    cin >> n >> m;
    ll ans = 0;

    for (int i = 1; i <= n; ++i)
    {
        ans = add(ans, power(m, i));
    }
    m %= P;
    ll prod = 1;
    ll cnt = 1;
    for (ll i = 1; i <= n; ++i)
    {
        if (prime(i))
            prod *= i;
        if (prod > m)
            break;
        cnt = mul(cnt, (m / prod) % P);
        ans = sub(ans, cnt);
    }
    cout << ans << endl;
}

int main(int argc, char *argv[])
{
    if (argc >= 2)
        freopen(argv[1], "r", stdin);
    ios_base::sync_with_stdio(0);
    cin.tie(nullptr);
    int tc = 1;
    // cin >> tc;
    while (tc--)
    {
        solve();
    }
}

#include<bits/stdc++.h>
#define int long long
#define endl "\n"
#define INF 0x3f3f3f3f3f3f3f3f
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
const int N=1e6;
const int mod = 1e9+7;
int a[N+5];
bool prime[N+5];
int n,m;
int ksm(int a,int x){
    int ans=1;
    while(x){
        if(x&1) ans=ans*a%mod;
        a=a*a%mod;
        x>>=1;
    }
    return ans;
}
void solve(){
    cin>>n>>m;
    for(int i=2;i<=n;i++)
	{
        if(prime[i]==0)
        for(int j=2*i;j<=n;j+=i)
            prime[j] = 1;
	}
    int now=1,temp=1,ans=0;
    for(int i=1;i<=n;i++)
	{
	    if(now<=1e12&&(prime[i]==0))
	        now*=i%mod;
	    temp=temp*(m/now)%mod;
	    ans=(mod+ans+ksm(m,i)-temp)%mod;
	}
    cout<<ans<<endl;
}
signed main(){
	IOS;
    solve();
}

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
#define N 300010
bool is_p[N];
int prime[N],tot;
long long ksm(long long a, long long b) {
    long long ans = 1, base = a%mod;
    while(b != 0) {
	if((b & 1 )!= 0) {
	    ans =ans*base%mod;
	}
	base =base*base%mod;
	b >>= 1;
    }
    return ans%mod;
}
inline int Eratosthenes(int n){
	for(int i=1;i<=n;i++) is_p[i]=1;
	memset(prime,0,sizeof(prime));
	is_p[1]=is_p[0]=0;
	for(int i=1;i<=n;i++){
		if(!is_p[i]) continue;
		prime[tot++]=i;//prime[]存储了[1,n]的所有质数
		for(int j=i*2;j<=n;j+=i) is_p[j]=0;//j为合数
	}
	return tot;
}
void solve(){
	ll n,m,ans=0;
	cin>>n>>m;
	Eratosthenes(n);
	for(int i=1;i<=n;i++) ans=(ans+ksm(m,i))%mod;
	// cout<<ans<<'\n';
	ll t=1,d=1;
	for(int i=1;i<=n;i++){
		if(is_p[i]) d*=i;
		// cout<<i<<" "<<is_p[i]<<' '<<d<<'\n';
		if(d>m) break;
		t=t*(m/d)%mod;
		ans=(ans-t+mod)%mod;
	}
	// cout<<d<<"\n";
	cout<<ans<<'\n';
}
int main(){
	int T=1;
	while(T--){
		solve();
	}
	return 0;
}

#include <bits/stdc++.h>
using namespace std;

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
template <typename T>
using o_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
template <typename T>
using o_multiset = tree<T, null_type, less_equal<T>, rb_tree_tag, tree_order_statistics_node_update>;
// member functions :
// 1. order_of_key(k) : number of elements strictly lesser than k
// 2. find_by_order(k) : k-th element in the set
template <class key, class value, class cmp = std::less<key>>
using o_map = __gnu_pbds::tree<key, value, cmp, __gnu_pbds::rb_tree_tag, __gnu_pbds::tree_order_statistics_node_update>;

using i64 = long long;
const i64 Mod = 1000000007;
const i64 MOD = 998244353;
const i64 Inf = 1E18;
const int dx[] = {0,  0, 1, -1, -1, -1,  1, 1};
const int dy[] = {1, -1, 0,  0, -1,  1, -1, 1};

//FOR unordered_map<int,int,custom_hash> TO AVOID FALTU TLE'S COZ OF ANTIHASHES.
struct custom_hash {
    static uint64_t splitmix64(uint64_t x) {
        // http://xorshift.di.unimi.it/splitmix64.c
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }
    size_t operator()(uint64_t x) const {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64(x + FIXED_RANDOM);
    }
};

template <typename T>
T roundup(T a, T b) {
    return(a / b + ((a ^ b) > 0 && a % b));
}

template <typename T>
T choose(T n, T r) {
    if(n < r) return 0LL;
    T res = 1;
    for(T e = 0 ; e < r ; e ++) {
        res = res * (n - e);
        res = res / (e + 1);
    }
    return res;
}

template <typename T>
bool expotwo(T n) {
    T val = (n & (n - 1));
    if(val == 0LL) return true;
    return false;
}

template <typename T>
T modexpo(T b, T e, T mod) {
    T ans = 1;
    while(e) {
        if(e & 1) ans = ((ans % mod) * (b % mod)) % mod;
        b = ((b % mod) * (b % mod)) % mod;
        e >>= 1;
    }
    return ans;
}

template <typename T>
T expo(T b, T e) {
    T ans = 1;
    while(e) {
        if(e & 1) ans = ans * b;
        b = b * b;
        e >>= 1;
    }
    return ans;
}

template <typename T>
bool eprime(T n) {
    if(n < 2) return false;
    for(T e = 2; e * e <= n; e ++) {
        if(n % e == 0) return false;
    }
    return true;
}

template <typename T>
bool eparity(T x, T y) {
    return !((x & 1) ^ (y & 1));
};

template <typename T>
void amax(T& a, T b) {
    a = max(a, b);
}

template <typename T>
void amin(T& a, T b) {
    a = min(a, b);
}

template <typename T>
void add(T& a, T b, T M) {
    a = ((a % M) + (b % M)) % M;
}

template <typename T>
void mul(T& a, T b, T M) {
    a = ((a % M) * (b % M)) % M;
}

template<typename T>
void sub(T& a, T b, T M) {
    a = (a - b + M) % M;
}

/* ************************************************************************ */

set <i64> prime;

void compute() {
    i64 mx = 1E5 + 20;
    vector <int> check(mx);
    for(i64 i = 2; i < mx; i ++) {
        if(check[i]) continue;
        prime.insert(i);
        for(i64 j = i + i; j < mx; j += i) check[j] = 1;
    }
}

void Solution()
{

    i64 n, m; cin >> n >> m;
    if(m == 1) return void(cout << n);
    i64 lcm = 1, ans = 0;
    vector <i64> minus(n + 1);
    minus[1] = m;
    for(i64 i = 2; i <= n; i ++) {
        i64 t = modexpo(m, i, MOD);
        if(lcm > m) {
            add(ans, t, MOD);
            continue;
        }
        if(prime.count(i)) lcm *= i;
        i64 d = m / lcm;
        minus[i] = (d % MOD) * (minus[i - 1] % MOD);
        minus[i] %= MOD;
        ans += (t - minus[i] + MOD) % MOD;
        ans %= MOD;
    }
    cout << (ans % MOD) << '\n';

}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    int Test_case = 1;   //cin >> Test_case;
    compute();
    while(Test_case --) Solution();

}

#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <math.h>
#include <cmath>
#include <algorithm>
#include <unordered_map>
#include <queue>
#include <set>
#include <cstdio>
#include <iomanip>
using namespace std;

typedef long long LL;
typedef pair<int, int> PII;

const int N = 100010, mod = 998244353;

LL n, m;
LL a[N];

LL gcd(LL a, LL b)
{
    return b ? gcd(b, a % b) : a;
}

LL qmi(LL a, LL b, LL p)
{
    LL res = 1;
    a = a % p;
    while (b)
    {
        if (b & 1)
            res = (res * a) % p;
        a = (a * a) % p;
        b >>= 1;
    }
    return res;
}

void solve()
{
    cin >> n >> m;
    LL rs = 1;
    for (int i = 1; i <= n; i++)
    {
        if (rs > m)
            a[i] = rs;
        else
        {

            if (gcd(rs, i) == 1)
                a[i] = (rs % mod * i) % mod;
            else
                a[i] = rs;
            if (rs > m)
                a[i] = m + 1;
            rs = a[i];
        }
    }
    LL ans = 0;
    for (int i = 2; i <= n; i++)
    {
        LL p = m % mod;
        for (int j = 2; j <= i; j++)
        {
            if (a[j] > m)
            {
                p = 0;
                break;
            }
            else
                p = (p % mod * (m / a[j]) % mod) % mod;
        }
        ans = (ans + qmi(m, i, mod) % mod) % mod;
        ans = ((ans - p) % mod + mod) % mod;
    }
    cout << ans << endl;
}

int main()
{
    cout.tie(nullptr);
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    //    cout << fixed << setprecision(10);
    int t = 1;
    // cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

#include <bits/stdc++.h>

using namespace std;

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"

#ifndef ATCODER_MODINT_HPP
#define ATCODER_MODINT_HPP 1

#include <cassert>
#include <numeric>
#include <type_traits>

#ifdef _MSC_VER
#include <intrin.h>
#endif

#ifndef ATCODER_INTERNAL_MATH_HPP
#define ATCODER_INTERNAL_MATH_HPP 1

#include <utility>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

// @param m `1 <= m`
// @return x mod m
constexpr long long safe_mod(long long x, long long m) {
  x %= m;
  if (x < 0) x += m;
  return x;
}

// Fast modular multiplication by barrett reduction
// Reference: https://en.wikipedia.org/wiki/Barrett_reduction
// NOTE: reconsider after Ice Lake
struct barrett {
  unsigned int _m;
  unsigned long long im;

  // @param m `1 <= m < 2^31`
  explicit barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}

  // @return m
  unsigned int umod() const { return _m; }

  // @param a `0 <= a < m`
  // @param b `0 <= b < m`
  // @return `a * b % m`
  unsigned int mul(unsigned int a, unsigned int b) const {
    // [1] m = 1
    // a = b = im = 0, so okay

    // [2] m >= 2
    // im = ceil(2^64 / m)
    // -> im * m = 2^64 + r (0 <= r < m)
    // let z = a*b = c*m + d (0 <= c, d < m)
    // a*b * im = (c*m + d) * im = c*(im*m) + d*im = c*2^64 + c*r + d*im
    // c*r + d*im < m * m + m * im < m * m + 2^64 + m <= 2^64 + m * (m + 1) < 2^64 * 2
    // ((ab * im) >> 64) == c or c + 1
    unsigned long long z = a;
    z *= b;
#ifdef _MSC_VER
    unsigned long long x;
    _umul128(z, im, &x);
#else
    unsigned long long x =
        (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
    unsigned int v = (unsigned int)(z - x * _m);
    if (_m <= v) v += _m;
    return v;
  }
};

// @param n `0 <= n`
// @param m `1 <= m`
// @return `(x ** n) % m`
constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
  if (m == 1) return 0;
  unsigned int _m = (unsigned int)(m);
  unsigned long long r = 1;
  unsigned long long y = safe_mod(x, m);
  while (n) {
    if (n & 1) r = (r * y) % _m;
    y = (y * y) % _m;
    n >>= 1;
  }
  return r;
}

// Reference:
// M. Forisek and J. Jancina,
// Fast Primality Testing for Integers That Fit into a Machine Word
// @param n `0 <= n`
constexpr bool is_prime_constexpr(int n) {
  if (n <= 1) return false;
  if (n == 2 || n == 7 || n == 61) return true;
  if (n % 2 == 0) return false;
  long long d = n - 1;
  while (d % 2 == 0) d /= 2;
  constexpr long long bases[3] = {2, 7, 61};
  for (long long a : bases) {
    long long t = d;
    long long y = pow_mod_constexpr(a, t, n);
    while (t != n - 1 && y != 1 && y != n - 1) {
      y = y * y % n;
      t <<= 1;
    }
    if (y != n - 1 && t % 2 == 0) {
      return false;
    }
  }
  return true;
}
template <int n>
constexpr bool is_prime = is_prime_constexpr(n);

// @param b `1 <= b`
// @return pair(g, x) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/g
constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
  a = safe_mod(a, b);
  if (a == 0) return {b, 0};

  // Contracts:
  // [1] s - m0 * a = 0 (mod b)
  // [2] t - m1 * a = 0 (mod b)
  // [3] s * |m1| + t * |m0| <= b
  long long s = b, t = a;
  long long m0 = 0, m1 = 1;

  while (t) {
    long long u = s / t;
    s -= t * u;
    m0 -= m1 * u;  // |m1 * u| <= |m1| * s <= b

    // [3]:
    // (s - t * u) * |m1| + t * |m0 - m1 * u|
    // <= s * |m1| - t * u * |m1| + t * (|m0| + |m1| * u)
    // = s * |m1| + t * |m0| <= b

    auto tmp = s;
    s = t;
    t = tmp;
    tmp = m0;
    m0 = m1;
    m1 = tmp;
  }
  // by [3]: |m0| <= b/g
  // by g != b: |m0| < b/g
  if (m0 < 0) m0 += b / s;
  return {s, m0};
}

// Compile time primitive root
// @param m must be prime
// @return primitive root (and minimum in now)
constexpr int primitive_root_constexpr(int m) {
  if (m == 2) return 1;
  if (m == 167772161) return 3;
  if (m == 469762049) return 3;
  if (m == 754974721) return 11;
  if (m == 998244353) return 3;
  int divs[20] = {};
  divs[0] = 2;
  int cnt = 1;
  int x = (m - 1) / 2;
  while (x % 2 == 0) x /= 2;
  for (int i = 3; (long long)(i)*i <= x; i += 2) {
    if (x % i == 0) {
      divs[cnt++] = i;
      while (x % i == 0) {
        x /= i;
      }
    }
  }
  if (x > 1) {
    divs[cnt++] = x;
  }
  for (int g = 2;; g++) {
    bool ok = true;
    for (int i = 0; i < cnt; i++) {
      if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
        ok = false;
        break;
      }
    }
    if (ok) return g;
  }
}
template <int m>
constexpr int primitive_root = primitive_root_constexpr(m);

// @param n `n < 2^32`
// @param m `1 <= m < 2^32`
// @return sum_{i=0}^{n-1} floor((ai + b) / m) (mod 2^64)
unsigned long long floor_sum_unsigned(unsigned long long n,
                                      unsigned long long m,
                                      unsigned long long a,
                                      unsigned long long b) {
  unsigned long long ans = 0;
  while (true) {
    if (a >= m) {
      ans += n * (n - 1) / 2 * (a / m);
      a %= m;
    }
    if (b >= m) {
      ans += n * (b / m);
      b %= m;
    }

    unsigned long long y_max = a * n + b;
    if (y_max < m) break;
    // y_max < m * (n + 1)
    // floor(y_max / m) <= n
    n = (unsigned long long)(y_max / m);
    b = (unsigned long long)(y_max % m);
    std::swap(m, a);
  }
  return ans;
}

}  // namespace internal

}  // namespace atcoder

#endif  // ATCODER_INTERNAL_MATH_HPP

#ifndef ATCODER_INTERNAL_TYPE_TRAITS_HPP
#define ATCODER_INTERNAL_TYPE_TRAITS_HPP 1

#include <cassert>
#include <numeric>
#include <type_traits>

namespace atcoder {

namespace internal {

#ifndef _MSC_VER
template <class T>
using is_signed_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value ||
                                  std::is_same<T, __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int128 =
    typename std::conditional<std::is_same<T, __uint128_t>::value ||
                                  std::is_same<T, unsigned __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using make_unsigned_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value,
                              __uint128_t,
                              unsigned __int128>;

template <class T>
using is_integral = typename std::conditional<std::is_integral<T>::value ||
                                                  is_signed_int128<T>::value ||
                                                  is_unsigned_int128<T>::value,
                                              std::true_type,
                                              std::false_type>::type;

template <class T>
using is_signed_int = typename std::conditional<(is_integral<T>::value &&
                                                 std::is_signed<T>::value) ||
                                                    is_signed_int128<T>::value,
                                                std::true_type,
                                                std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<(is_integral<T>::value &&
                               std::is_unsigned<T>::value) ||
                                  is_unsigned_int128<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<
    is_signed_int128<T>::value,
    make_unsigned_int128<T>,
    typename std::conditional<std::is_signed<T>::value,
                              std::make_unsigned<T>,
                              std::common_type<T>>::type>::type;

#else

template <class T>
using is_integral = typename std::is_integral<T>;

template <class T>
using is_signed_int =
    typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<is_integral<T>::value &&
                                  std::is_unsigned<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<is_signed_int<T>::value,
                                              std::make_unsigned<T>,
                                              std::common_type<T>>::type;

#endif

template <class T>
using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;

template <class T>
using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;

template <class T>
using to_unsigned_t = typename to_unsigned<T>::type;

}  // namespace internal

}  // namespace atcoder

#endif  // ATCODER_INTERNAL_TYPE_TRAITS_HPP

namespace atcoder {

namespace internal {

struct modint_base {};
struct static_modint_base : modint_base {};

template <class T>
using is_modint = std::is_base_of<modint_base, T>;
template <class T>
using is_modint_t = std::enable_if_t<is_modint<T>::value>;

}  // namespace internal

template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
struct static_modint : internal::static_modint_base {
  using mint = static_modint;

 public:
  static constexpr int mod() { return m; }
  static mint raw(int v) {
    mint x;
    x._v = v;
    return x;
  }

  static_modint() : _v(0) {}
  template <class T, internal::is_signed_int_t<T>* = nullptr>
  static_modint(T v) {
    long long x = (long long)(v % (long long)(umod()));
    if (x < 0) x += umod();
    _v = (unsigned int)(x);
  }
  template <class T, internal::is_unsigned_int_t<T>* = nullptr>
  static_modint(T v) {
    _v = (unsigned int)(v % umod());
  }

  unsigned int val() const { return _v; }

  mint& operator++() {
    _v++;
    if (_v == umod()) _v = 0;
    return *this;
  }
  mint& operator--() {
    if (_v == 0) _v = umod();
    _v--;
    return *this;
  }
  mint operator++(int) {
    mint result = *this;
    ++*this;
    return result;
  }
  mint operator--(int) {
    mint result = *this;
    --*this;
    return result;
  }

  mint& operator+=(const mint& rhs) {
    _v += rhs._v;
    if (_v >= umod()) _v -= umod();
    return *this;
  }
  mint& operator-=(const mint& rhs) {
    _v -= rhs._v;
    if (_v >= umod()) _v += umod();
    return *this;
  }
  mint& operator*=(const mint& rhs) {
    unsigned long long z = _v;
    z *= rhs._v;
    _v = (unsigned int)(z % umod());
    return *this;
  }
  mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

  mint operator+() const { return *this; }
  mint operator-() const { return mint() - *this; }

  mint pow(long long n) const {
    assert(0 <= n);
    mint x = *this, r = 1;
    while (n) {
      if (n & 1) r *= x;
      x *= x;
      n >>= 1;
    }
    return r;
  }
  mint inv() const {
    if (prime) {
      assert(_v);
      return pow(umod() - 2);
    } else {
      auto eg = internal::inv_gcd(_v, m);
      assert(eg.first == 1);
      return eg.second;
    }
  }

  friend mint operator+(const mint& lhs, const mint& rhs) {
    return mint(lhs) += rhs;
  }
  friend mint operator-(const mint& lhs, const mint& rhs) {
    return mint(lhs) -= rhs;
  }
  friend mint operator*(const mint& lhs, const mint& rhs) {
    return mint(lhs) *= rhs;
  }
  friend mint operator/(const mint& lhs, const mint& rhs) {
    return mint(lhs) /= rhs;
  }
  friend bool operator==(const mint& lhs, const mint& rhs) {
    return lhs._v == rhs._v;
  }
  friend bool operator!=(const mint& lhs, const mint& rhs) {
    return lhs._v != rhs._v;
  }

 private:
  unsigned int _v;
  static constexpr unsigned int umod() { return m; }
  static constexpr bool prime = internal::is_prime<m>;
};

template <int id>
struct dynamic_modint : internal::modint_base {
  using mint = dynamic_modint;

 public:
  static int mod() { return (int)(bt.umod()); }
  static void set_mod(int m) {
    assert(1 <= m);
    bt = internal::barrett(m);
  }
  static mint raw(int v) {
    mint x;
    x._v = v;
    return x;
  }

  dynamic_modint() : _v(0) {}
  template <class T, internal::is_signed_int_t<T>* = nullptr>
  dynamic_modint(T v) {
    long long x = (long long)(v % (long long)(mod()));
    if (x < 0) x += mod();
    _v = (unsigned int)(x);
  }
  template <class T, internal::is_unsigned_int_t<T>* = nullptr>
  dynamic_modint(T v) {
    _v = (unsigned int)(v % mod());
  }

  unsigned int val() const { return _v; }

  mint& operator++() {
    _v++;
    if (_v == umod()) _v = 0;
    return *this;
  }
  mint& operator--() {
    if (_v == 0) _v = umod();
    _v--;
    return *this;
  }
  mint operator++(int) {
    mint result = *this;
    ++*this;
    return result;
  }
  mint operator--(int) {
    mint result = *this;
    --*this;
    return result;
  }

  mint& operator+=(const mint& rhs) {
    _v += rhs._v;
    if (_v >= umod()) _v -= umod();
    return *this;
  }
  mint& operator-=(const mint& rhs) {
    _v += mod() - rhs._v;
    if (_v >= umod()) _v -= umod();
    return *this;
  }
  mint& operator*=(const mint& rhs) {
    _v = bt.mul(_v, rhs._v);
    return *this;
  }
  mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

  mint operator+() const { return *this; }
  mint operator-() const { return mint() - *this; }

  mint pow(long long n) const {
    assert(0 <= n);
    mint x = *this, r = 1;
    while (n) {
      if (n & 1) r *= x;
      x *= x;
      n >>= 1;
    }
    return r;
  }
  mint inv() const {
    auto eg = internal::inv_gcd(_v, mod());
    assert(eg.first == 1);
    return eg.second;
  }

  friend mint operator+(const mint& lhs, const mint& rhs) {
    return mint(lhs) += rhs;
  }
  friend mint operator-(const mint& lhs, const mint& rhs) {
    return mint(lhs) -= rhs;
  }
  friend mint operator*(const mint& lhs, const mint& rhs) {
    return mint(lhs) *= rhs;
  }
  friend mint operator/(const mint& lhs, const mint& rhs) {
    return mint(lhs) /= rhs;
  }
  friend bool operator==(const mint& lhs, const mint& rhs) {
    return lhs._v == rhs._v;
  }
  friend bool operator!=(const mint& lhs, const mint& rhs) {
    return lhs._v != rhs._v;
  }

 private:
  unsigned int _v;
  static internal::barrett bt;
  static unsigned int umod() { return bt.umod(); }
};
template <int id>
internal::barrett dynamic_modint<id>::bt(998244353);

using modint998244353 = static_modint<998244353>;
using modint1000000007 = static_modint<1000000007>;
using modint = dynamic_modint<-1>;

namespace internal {

template <class T>
using is_static_modint = std::is_base_of<internal::static_modint_base, T>;

template <class T>
using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;

template <class>
struct is_dynamic_modint : public std::false_type {};
template <int id>
struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};

template <class T>
using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;

}  // namespace internal

}  // namespace atcoder

#endif  // ATCODER_MODINT_HPP

#ifndef ATCODER_INTERNAL_BITOP_HPP
#define ATCODER_INTERNAL_BITOP_HPP 1

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

// @param n `0 <= n`
// @return minimum non-negative `x` s.t. `n <= 2**x`
int ceil_pow2(int n) {
  int x = 0;
  while ((1U << x) < (unsigned int)(n)) x++;
  return x;
}

// @param n `1 <= n`
// @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`
constexpr int bsf_constexpr(unsigned int n) {
  int x = 0;
  while (!(n & (1 << x))) x++;
  return x;
}

// @param n `1 <= n`
// @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`
int bsf(unsigned int n) {
#ifdef _MSC_VER
  unsigned long index;
  _BitScanForward(&index, n);
  return index;
#else
  return __builtin_ctz(n);
#endif
}

}  // namespace internal

}  // namespace atcoder

#endif  // ATCODER_INTERNAL_BITOP_HPP

#ifndef ATCODER_SEGTREE_HPP
#define ATCODER_SEGTREE_HPP 1

namespace atcoder {

template <class S, S (*op)(S, S), S (*e)()>
struct segtree {
 public:
  segtree() : segtree(0) {}
  explicit segtree(int n) : segtree(std::vector<S>(n, e())) {}
  explicit segtree(const std::vector<S>& v) : _n(int(v.size())) {
    log = internal::ceil_pow2(_n);
    size = 1 << log;
    d = std::vector<S>(2 * size, e());
    for (int i = 0; i < _n; i++) d[size + i] = v[i];
    for (int i = size - 1; i >= 1; i--) {
      update(i);
    }
  }

  void set(int p, S x) {
    assert(0 <= p && p < _n);
    p += size;
    d[p] = x;
    for (int i = 1; i <= log; i++) update(p >> i);
  }

  S get(int p) const {
    assert(0 <= p && p < _n);
    return d[p + size];
  }

  S prod(int l, int r) const {
    assert(0 <= l && l <= r && r <= _n);
    S sml = e(), smr = e();
    l += size;
    r += size;

    while (l < r) {
      if (l & 1) sml = op(sml, d[l++]);
      if (r & 1) smr = op(d[--r], smr);
      l >>= 1;
      r >>= 1;
    }
    return op(sml, smr);
  }

  S all_prod() const { return d[1]; }

  template <bool (*f)(S)>
  int max_right(int l) const {
    return max_right(l, [](S x) { return f(x); });
  }
  template <class F>
  int max_right(int l, F f) const {
    assert(0 <= l && l <= _n);
    assert(f(e()));
    if (l == _n) return _n;
    l += size;
    S sm = e();
    do {
      while (l % 2 == 0) l >>= 1;
      if (!f(op(sm, d[l]))) {
        while (l < size) {
          l = (2 * l);
          if (f(op(sm, d[l]))) {
            sm = op(sm, d[l]);
            l++;
          }
        }
        return l - size;
      }
      sm = op(sm, d[l]);
      l++;
    } while ((l & -l) != l);
    return _n;
  }

  template <bool (*f)(S)>
  int min_left(int r) const {
    return min_left(r, [](S x) { return f(x); });
  }
  template <class F>
  int min_left(int r, F f) const {
    assert(0 <= r && r <= _n);
    assert(f(e()));
    if (r == 0) return 0;
    r += size;
    S sm = e();
    do {
      r--;
      while (r > 1 && (r % 2)) r >>= 1;
      if (!f(op(d[r], sm))) {
        while (r < size) {
          r = (2 * r + 1);
          if (f(op(d[r], sm))) {
            sm = op(d[r], sm);
            r--;
          }
        }
        return r + 1 - size;
      }
      sm = op(d[r], sm);
    } while ((r & -r) != r);
    return 0;
  }

 private:
  int _n, size, log;
  std::vector<S> d;

  void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
};

}  // namespace atcoder

#endif  // ATCODER_SEGTREE_HPP

#ifndef ATCODER_LAZYSEGTREE_HPP
#define ATCODER_LAZYSEGTREE_HPP 1

#include <algorithm>
#include <cassert>
#include <iostream>
#include <vector>

namespace atcoder {

template <class S,
          S (*op)(S, S),
          S (*e)(),
          class F,
          S (*mapping)(F, S),
          F (*composition)(F, F),
          F (*id)()>
struct lazy_segtree {
 public:
  lazy_segtree() : lazy_segtree(0) {}
  explicit lazy_segtree(int n) : lazy_segtree(std::vector<S>(n, e())) {}
  explicit lazy_segtree(const std::vector<S>& v) : _n(int(v.size())) {
    log = internal::ceil_pow2(_n);
    size = 1 << log;
    d = std::vector<S>(2 * size, e());
    lz = std::vector<F>(size, id());
    for (int i = 0; i < _n; i++) d[size + i] = v[i];
    for (int i = size - 1; i >= 1; i--) {
      update(i);
    }
  }

  void set(int p, S x) {
    assert(0 <= p && p < _n);
    p += size;
    for (int i = log; i >= 1; i--) push(p >> i);
    d[p] = x;
    for (int i = 1; i <= log; i++) update(p >> i);
  }

  S get(int p) {
    assert(0 <= p && p < _n);
    p += size;
    for (int i = log; i >= 1; i--) push(p >> i);
    return d[p];
  }

  S prod(int l, int r) {
    assert(0 <= l && l <= r && r <= _n);
    if (l == r) return e();

    l += size;
    r += size;

    for (int i = log; i >= 1; i--) {
      if (((l >> i) << i) != l) push(l >> i);
      if (((r >> i) << i) != r) push((r - 1) >> i);
    }

    S sml = e(), smr = e();
    while (l < r) {
      if (l & 1) sml = op(sml, d[l++]);
      if (r & 1) smr = op(d[--r], smr);
      l >>= 1;
      r >>= 1;
    }

    return op(sml, smr);
  }

  S all_prod() { return d[1]; }

  void apply(int p, F f) {
    assert(0 <= p && p < _n);
    p += size;
    for (int i = log; i >= 1; i--) push(p >> i);
    d[p] = mapping(f, d[p]);
    for (int i = 1; i <= log; i++) update(p >> i);
  }
  void apply(int l, int r, F f) {
    assert(0 <= l && l <= r && r <= _n);
    if (l == r) return;

    l += size;
    r += size;

    for (int i = log; i >= 1; i--) {
      if (((l >> i) << i) != l) push(l >> i);
      if (((r >> i) << i) != r) push((r - 1) >> i);
    }

    {
      int l2 = l, r2 = r;
      while (l < r) {
        if (l & 1) all_apply(l++, f);
        if (r & 1) all_apply(--r, f);
        l >>= 1;
        r >>= 1;
      }
      l = l2;
      r = r2;
    }

    for (int i = 1; i <= log; i++) {
      if (((l >> i) << i) != l) update(l >> i);
      if (((r >> i) << i) != r) update((r - 1) >> i);
    }
  }

  template <bool (*g)(S)>
  int max_right(int l) {
    return max_right(l, [](S x) { return g(x); });
  }
  template <class G>
  int max_right(int l, G g) {
    assert(0 <= l && l <= _n);
    assert(g(e()));
    if (l == _n) return _n;
    l += size;
    for (int i = log; i >= 1; i--) push(l >> i);
    S sm = e();
    do {
      while (l % 2 == 0) l >>= 1;
      if (!g(op(sm, d[l]))) {
        while (l < size) {
          push(l);
          l = (2 * l);
          if (g(op(sm, d[l]))) {
            sm = op(sm, d[l]);
            l++;
          }
        }
        return l - size;
      }
      sm = op(sm, d[l]);
      l++;
    } while ((l & -l) != l);
    return _n;
  }

  template <bool (*g)(S)>
  int min_left(int r) {
    return min_left(r, [](S x) { return g(x); });
  }
  template <class G>
  int min_left(int r, G g) {
    assert(0 <= r && r <= _n);
    assert(g(e()));
    if (r == 0) return 0;
    r += size;
    for (int i = log; i >= 1; i--) push((r - 1) >> i);
    S sm = e();
    do {
      r--;
      while (r > 1 && (r % 2)) r >>= 1;
      if (!g(op(d[r], sm))) {
        while (r < size) {
          push(r);
          r = (2 * r + 1);
          if (g(op(d[r], sm))) {
            sm = op(d[r], sm);
            r--;
          }
        }
        return r + 1 - size;
      }
      sm = op(d[r], sm);
    } while ((r & -r) != r);
    return 0;
  }

 private:
  int _n, size, log;
  std::vector<S> d;
  std::vector<F> lz;

  void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
  void all_apply(int k, F f) {
    d[k] = mapping(f, d[k]);
    if (k < size) lz[k] = composition(f, lz[k]);
  }
  void push(int k) {
    all_apply(2 * k, lz[k]);
    all_apply(2 * k + 1, lz[k]);
    lz[k] = id();
  }
};

}  // namespace atcoder

#endif  // ATCODER_LAZYSEGTREE_HPP

ostream& operator<<(ostream& os, atcoder::modint1000000007& x) { return os << x.val(); }
ostream& operator<<(ostream& os, atcoder::modint998244353& x) { return os << x.val(); }

template <typename A, typename B>
ostream& operator<<(ostream& os, const pair<A, B>& p) { return os << '(' << p.first << ", " << p.second << ')'; }
void print() { cout << endl; }
template <typename T, typename... Tail>
void print(T&& seq, Tail... tail) {
  if constexpr (ranges::range<T> && !convertible_to<T, string>)
    for (const auto& x : seq) cout << x << ' ';
  else
    cout << seq;
  cout << ' ';
  print(tail...);
}

#pragma GCC diagnostic pop

using S = int;
S op(S l, S r) { return l + r; }
S e() { return 0; }
// atcoder::segtree<S, op, e> segTree(vector<S>(N, e()));
// atcoder::lazy_segtree<S, op, e, F, mapping, composition, id> segTree(vector<S>(N, e()));

using modint = atcoder::modint998244353;

vector<int> smallestPrimeFactor;
void initPrimes(int n) {
  smallestPrimeFactor.assign(n, -1);
  for (int64_t i = 2; i < n; i++) {
    if (smallestPrimeFactor[i] == -1) {
      smallestPrimeFactor[i] = i;
      for (int64_t j = i * i; j < n; j += i) {
        if (smallestPrimeFactor[j] == -1) {
          smallestPrimeFactor[j] = i;
        }
      }
    }
  }
}

bool isPrime(int n) {
  assert(n < ssize(smallestPrimeFactor));
  return smallestPrimeFactor[n] == n;
}

map<int, int> primeFactors(int n) {
  map<int, int> freq;
  while (n != 1) {
    int x = smallestPrimeFactor[n];
    n /= x;
    freq[x] += 1;
  }
  return freq;
}
void solve() {
  int64_t N, M;
  cin >> N >> M;
  if (M == 1) {
    print(0);
    return;
  }

  int64_t INF = 1e18;
  vector<int64_t> pref(N + 1, INF);
  pref[0] = 1;
  for (int i = 1; i <= N; i++) {
    int64_t extra = 1;
    if (i == 1 || isPrime(i)) {
      extra = i;
    }
    pref[i] = pref[i - 1] * extra;
    if (pref[i] > M) {
      break;
    }
  }

  vector<int64_t> ways(N + 1, INF);
  ways[0] = 0;

  modint n = N;
  modint m = M;
  modint ans = ((m.pow(N + 1) - 1) / (m - 1)) - 1;
  modint cum = 1;
  for (int i = 1; i <= N; i++) {
    ways[i] = M / pref[i];
    cum *= ways[i];
    ans -= cum;
  }

  print(ans);
}

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);
  cin.exceptions(ios::badbit | ios::failbit);
  cout << fixed << setprecision(15);
  initPrimes(1e6);
  int TC = 1;
  while (TC--) {
    solve();
  }

  return 0;
}

# include <bits/stdc++.h>
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define x first
#define y second
#define endl '\n'
#define int long long
using namespace std;
typedef pair<int, int> PII;
const int N = 1e6 + 10;
const int M = 2e5 + 10;
const int INF = 0x3f3f3f3f;
const double INFF = 0x7f7f7f7f7f7f7f7f;
const int mod = 1e9 + 7;
int n, m, cnt;
int p[N];
bool st[N];
int non[N], sum[N];
void get()
{
    st[1] = true;
    for(int i = 2;i <= N - 10;i ++)
    {
        if(!st[i])p[cnt ++] = i;
        for(int j = 0;p[j] <= (N - 10) / i;j ++)
        {
            st[p[j] * i] = true;
            if(i % p[j] == 0)break;
        }
    }
}

signed main()
{
    ios;
    get();
    cin >> n >> m;
    int lc = 1;
    non[1] = m % mod;
    for (int i = 2; i <= n; i++) {
        if (!st[i]) lc *= i;
        int cnt = m / lc;
        non[i] = non[i - 1] * (cnt % mod) % mod;
    }

    sum[1] = m % mod;
    for (int i = 2; i <= n; i++) {
        sum[i] = sum[i - 1] * (m % mod) % mod;
    }

    int ans = 0;
    for (int i = 1; i <= n; i++) {
        ans = (ans + sum[i] - non[i]) % mod;
    }

    cout << (ans + mod) % mod;
    return 0;
}

#include <bits/stdc++.h>

/*
 I don't need to fight
 To prove I'm right
 I don't need to be forgiven.
 Yeah, yeah, yeah, yeah, yeah
 */

using namespace std;
typedef long long ll;

void solve() {
    ll mod = 998244353;
    ll n, m;
    cin >> n >> m;

    vector<bool> p(n + 10, true);
    p[0] = p[1] = false;

    for (ll i = 2; i < p.size(); ++i) {
        if (p[i]) {
            for (ll j = i * i; j < p.size(); j += i) {
                p[j] = false;
            }
        }
    }

    vector<ll> dp(n + 1), deg(n + 1, 1ll);

    ll b = m;
    for (ll i = 1; i <= n; ++i) {
        deg[i] = (deg[i - 1] * m) % mod;
    }

    deg[0] = 1;
    ll q = 1;
    for (ll i = 1; i <= n; ++i) {
        if (p[i]) {
            if (q > m) {
                b = 0;
            } else {
                q *= i;
                b = m / q;
            }
        }

        dp[i] = (dp[i - 1] * m) % mod + (mod + deg[i - 1] - dp[i - 1]) % mod * (m - b) % mod;
        dp[i] = (dp[i] % mod + mod) % mod;
    }

    ll ans = 0;
    for (ll i = 0; i <= n; ++i) {
        ans += dp[i];
        ans %= mod;
    }
    cout << ans << "\n";
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    ll tst = 1;

    //cin >> tst;
    while (tst--) {
        solve();
    }

    return 0;
}