#include <iostream>

using namespace std;

typedef long long ll;

const int MOD = 998244353; 

struct Modint {
  ll val;
  
  Modint (ll _val = 0)
    : val(_val % MOD) {}

  Modint operator+ (Modint other) const {
    return Modint(val + other.val);
  }

  void operator+= (Modint other) {
    val += other.val;
    val %= MOD;
  }

  Modint operator- () const {
    return Modint(MOD - val);
  }

  Modint operator- (Modint other) const {
    return Modint(val + MOD - other.val);
  }

  void operator-= (Modint other) {
    val += MOD - other.val;
    val %= MOD;
  }

  Modint operator* (Modint other) const {
    return Modint(val * other.val);
  }

  void operator*= (Modint other) {
    val *= other.val;
    val %= MOD;
  }

  bool operator== (Modint other) const {
    return val == other.val;
  }

  bool operator!= (Modint other) const {
    return val != other.val;
  }
};

Modint exp (Modint a, int k) {
  if (k == 0) {
    return Modint(1);
  } else if (k % 2 == 0) {
    Modint half = exp(a, k / 2);
    return half * half;
  } else {
    return a * exp(a, k - 1);
  }
}

Modint inv (Modint a) {
  return exp(a, MOD - 2);
}

ostream& operator<< (ostream& out, Modint p) {
  out << p.val;
  return out;
}


const int MAX_N = 2e5 + 5;
const int MAX_LG = 20;

Modint dp [MAX_LG][MAX_N]; // dp[k][i] is # of ways to write i as a product of k non-1 divisors

Modint fact [MAX_N];
Modint ifact [MAX_N];

Modint choose (int n, int k) {
  return fact[n] * ifact[k] * ifact[n - k];
}

int main () {
  fact[0] = Modint(1);
  for (int i = 1; i < MAX_N; i++) {
    fact[i] = fact[i - 1] * Modint(i);
  }

  for (int i = 0; i < MAX_N; i++) {
    ifact[i] = inv(fact[i]);
  }
  
  int n, m;
  cin >> n >> m;

  dp[0][1] = Modint(1);
  for (int k = 0; k < MAX_LG - 1; k++) {
    for (int i = 1; i <= m; i++) {
      for (int j = 2 * i; j <= m; j += i) {
        dp[k + 1][j] += dp[k][i];
      }
    }
  }

  Modint ans (0);
  for (int i = 1; i <= m; i++) {
    for (int k = 0; k < MAX_LG; k++) {
      // k nonones, n - k ones
      if (n - k < 0) {
        continue;
      }

      ans += choose(n, k) * dp[k][i];
    }
  }
  cout << ans << endl;
}

#include <bits/stdc++.h>
using namespace std;
 
#define REP(i, s) for (int i = 0; i < s; ++i)
#define ALL(v) (v).begin(), (v).end()
#define COUT(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << endl
#define EACH(i, s) for (__typeof__((s).begin()) i = (s).begin(); i != (s).end(); ++i)
#define DEBUG
#define int long long
#define INF 1e18
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
template<class T1, class T2> ostream& operator << (ostream &s, pair<T1,T2> P)
{ return s << '<' << P.first << ", " << P.second << '>'; }
template<class T> ostream& operator << (ostream &s, vector<T> P)
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T> ostream& operator << (ostream &s, vector<vector<T> > P)
{ for (int i = 0; i < P.size(); ++i) { s << endl << P[i]; } return s << endl; }
template<class T> ostream& operator << (ostream &s, set<T> P)
{ EACH(it, P) { s << "<" << *it << "> "; } return s << endl; }
template<class T1, class T2> ostream& operator << (ostream &s, map<T1,T2> P)
{ EACH(it, P) { s << "<" << it->first << "->" << it->second << "> "; } return s << endl; }
template<class T>void show(vector<T>v){for (int i = 0; i < v.size(); i++){cerr<<v[i]<<" ";}cerr<<"\n";}
typedef long long ll;

ll MOD=998244353;
ll add(ll x, ll y)
{
    x += y;
    if (x >= MOD)
        return x - MOD;
    return x;
}
ll sub(ll x, ll y)
{
    x -= y;
    if (x < 0)
        return x + MOD;
    return x;
}
ll mult(ll x, ll y)
{
    return (x * y) % MOD;
}
ll bin_pow(ll x, ll p)
{
    if (p == 0)
        return 1;
    if (p & 1)
        return mult(x, bin_pow(x, p - 1));
    return bin_pow(mult(x, x), p / 2);
}

const int MAX = 510000;

long long fac[MAX], finv[MAX], inv[MAX];

// テーブルを作る前処理
void COMinit()
{
    fac[0] = fac[1] = 1;
    finv[0] = finv[1] = 1;
    inv[1] = 1;
    for (int i = 2; i < MAX; i++)
    {
        fac[i] = fac[i - 1] * i % MOD;
        inv[i] = MOD - inv[MOD % i] * (MOD / i) % MOD;
        finv[i] = finv[i - 1] * inv[i] % MOD;
    }
}

// 二項係数計算
long long COM(int n, int k)
{
    if (n < k)
        return 0;
    if (n < 0 || k < 0)
        return 0;
    return fac[n] * (finv[k] * finv[n - k] % MOD) % MOD;
}


signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n,m;
    cin>>n>>m;
    COMinit();
    int ans=0;
    /*vector<int>pre(30);
    for (int i = 0; i <= 30; i++)
    {
        int cnt=0;
        for(int j=n;j>=1; j--){
            cnt+=bin_pow(j,i);
            cnt%=MOD;
        }
        pre[i]=cnt;
    }
    */
    for (int i = 1; i <= m; i++)
    {
        int N = i;
        int c=2;
        int cnt=0;
        int res=1;
        map<int,int>mp;
        while(c*c<=N){
            if(N%c==0){
                mp[c]++;
                cnt++;
                N/=c;
            }
            else{

                //if(cnt>0) res *= COM(n-1+cnt, cnt);
                res%=MOD;
                c++;
                cnt=0;
            }
        }
        if(N!=1) {
            mp[N]++;
            cnt++;
        }
        for(auto &u : mp){
            int x =u.second;
            res*=COM(n-1+x,x);
            res%=MOD;
        }
        //if(cnt>0) res*=COM(n-1+cnt, cnt);
        res%=MOD;
        //cerr<<i<<" "<<res<<endl;
        ans+=res;
        ans%=MOD;
    }
    cout<<(ans)%MOD<<endl;
    return 0;
}