#include <iostream>

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <deque>
#include <stack>
#include <queue>
#include <array>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <random>
#include <chrono>
#include <utility>
#include <numeric>
#include <cstdlib>
#include <cstring>
#include <climits>
#include <sstream>
#include <assert.h>
#include <iomanip>
#include <algorithm>
#include <functional>
#include <unordered_map>

using namespace std;
struct _ { ios_base::Init i; _() { ios_base::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL); } } _;

#define sim template < class c
#define ris return * this
#define dor > debug & operator <<
#define eni(x) sim > typename \
  enable_if<sizeof dud<c>(0) x 1, debug&>::type operator<<(c i) {
sim > struct rge { c b, e; };
sim > rge<c> range(c i, c j) { return rge<c> {i, j}; }
sim > auto dud(c* x) -> decltype(cerr << *x, 0);
sim > char dud(...);
struct debug {
#ifdef HOME
	~debug() { cerr << endl; }
	eni( != ) cerr << boolalpha << i; ris;
}
eni( == ) ris << range(begin(i), end(i));
}
sim, class b dor(pair < b, c > d) {
	ris << "(" << d.first << ", " << d.second << ")";
}
sim dor(rge<c> d) {
	*this << "[";
	for (auto it = d.b; it != d.e; ++it)
		*this << ", " + 2 * (it == d.b) << *it;
	ris << "]";
}
#else
	sim dor(const c&) { ris; }
#endif
};
#define imie(...) " [" << #__VA_ARGS__ ": " << (__VA_ARGS__) << "] "


#define ff first
#define ss second
#define REP(i,st,en) for (int i = st; i <= en; i++)
#define REPR(i,st,en) for (int i = st; i >= en; i--)

const int MOD = 998244353;

class Modint {
public:
	long long val;

	Modint (long long _val = 0) {
		if (_val >= MOD) _val %= MOD;
		val = _val;
	}

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

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

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

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

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

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

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

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

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

Modint exp (Modint a, long long k) {
	Modint res = 1;
	while (k) {
		if (k & 1) res *= a;
		a *= a;
		k >>= 1;
	}
	return res;
}

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

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

const int maxn = 2e5;

vector<Modint> fact(maxn + 1, 1);
vector<Modint> inv_fact(maxn + 1, 1);

void preC() {
	for (int i = 2; i <= maxn; i++) {
		fact[i] = fact[i - 1] * i;
	}
	inv_fact[maxn] = inv(fact[maxn]);
	for (int i = maxn - 1; i >= 0; i--) inv_fact[i] = inv_fact[i + 1] * (i + 1);
}

Modint C(int n, int r) { // nCr % MOD
	if (n < r) return 0;
	return fact[n] * inv_fact[r] * inv_fact[n - r];
}


class MainClass {
public:

	void solve() {

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

		if (m == 1) {
			cout << 1;
			return;
		}

		int lgm = log2(m) + 1;

		Modint ans = 0;
		vector<Modint> dp(m + 1, 1);

		for (int i = 1; i <= lgm; i++) {
			vector<Modint> new_dp(m + 1, 0);
			Modint curr = 0;

			for (int j = 1; j <= m; j++) {
				for (int k = 2 * j; k <= m; k += j) new_dp[k] += dp[j];
				curr += dp[j];
			}

			ans += C(n - 1, i - 1) * curr;
			swap(dp, new_dp);
		}

		cout << ans;


		return;
	}
};

int main() {
	preC();

	int test = 1; //cin >> test;
	for (int tst = 1; tst <= test; ++tst) {
		MainClass Ausmosian;

		Ausmosian.solve();
		cout << "\n";
	}

	return 0;
}
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, n) for (ll i = 0; i < (ll)(n); i++)
#define rep2(i, s, n) for (ll i = (s); i < (ll)(n); i++)
#define all(v) begin(v), end(v)
#define sz(v) v.size()
#define INF 1e18+9
#define EPSILON 1e-14
template <typename T>
bool chmax(T &a, const T& b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <typename T>
bool chmin(T &a, const T& b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}

// auto mod int
// https://youtu.be/L8grWxBlIZ4?t=9858
// https://youtu.be/ERZuLAxZffQ?t=4807 : optimize
// https://youtu.be/8uowVvQ_-Mo?t=1329 : division
const int mod = 998244353;
struct mint {
  ll x; // typedef long long ll;
  mint(ll x=0):x((x%mod+mod)%mod){}
  mint operator-() const { return mint(-x);}
  mint& operator+=(const mint a) {
  if ((x += a.x) >= mod) x -= mod;
  return *this;
  }
  mint& operator-=(const mint a) {
  if ((x += mod-a.x) >= mod) x -= mod;
  return *this;
  }
  mint& operator*=(const mint a) { (x *= a.x) %= mod; return *this;}
  mint operator+(const mint a) const { return mint(*this) += a;}
  mint operator-(const mint a) const { return mint(*this) -= a;}
  mint operator*(const mint a) const { return mint(*this) *= a;}
  mint pow(ll t) const {
  if (!t) return 1;
  mint a = pow(t>>1);
  a *= a;
  if (t&1) a *= *this;
  return a;
  }
  // for prime mod
  mint inv() const { return pow(mod-2);}
  mint& operator/=(const mint a) { return *this *= a.inv();}
  mint operator/(const mint a) const { return mint(*this) /= a;}
};
istream& operator>>(istream& is, const mint& a) { return is >> a.x;}
ostream& operator<<(ostream& os, const mint& a) { return os << a.x;}

vector<pair<long long, long long> > prime_factorize(long long N) {
  vector<pair<long long, long long> > res;
  for (long long a = 2; a * a <= N; ++a) {
    if (N % a != 0) continue;
    long long ex = 0; // 指数
    // 割れる限り割り続ける
    while (N % a == 0) {
     ++ex;
      N /= a;
    }
    // その結果を push
    res.push_back({a, ex});
  }
  // 最後に残った数について
  if (N != 1) res.push_back({N, 1});
  return res;
}

vector<mint> fac(2000003, 1);
void calc(int n){
  rep(i, n){
    fac.at(i+1) = fac.at(i) * (i+1);
  }
  return;
}

mint mcom(int n, int k){ // nCk
  if(n-k < 0){
      return 0;
  }
  mint a = fac.at(n);
  mint b = fac.at(k);
  mint d = fac.at(n-k);
  mint ans = a / (b * d);
  return ans;
}

int main()
{
    ll N, M;
    cin >> N >> M;
    calc(2000000);
    mint ans = 0;
    rep2(i, 1, M+1){
        vector<pair<ll, ll>> pf = prime_factorize(i);
        mint t = 1;
        for(auto p : pf){
            t *= mcom(p.second+N-1, p.second);
        }
        ans += t;
    }
    cout << ans << '\n';
}