#pragma GCC optimize("O3")
//#pragma GCC optimize("unroll-loops")
// #pragma GCC target("avx2")
// 293206GT
#include <array>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <climits>
#include <limits>
#include <set>
#include <map>
#include <queue>
//#include <unordered_map>
//#include <unordered_set>
//#include <unordered_set>
//#include <stack>
#include <string>
#include <algorithm>
#include <random>
#include <bitset>
#include <chrono>
//#include <cstdlib>
//#include <cstring>

//#include <bits/extc++.h>
//using namespace __gnu_pbds;
//template<class T>
//using OrderedSet = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
using ll = long long;
// #define int ll
// #define int long long
using namespace std;
#define put(a) cout << (a) << '\n'
#define sqr(x) ((x) * (x))
typedef pair<int, int> pii;
typedef long double ld;
typedef pair<ld, ld> pld;
typedef unsigned long long ull;

typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<pii> vpii;
#define ts to_string
#define sts string ts

sts(string s) { return s; }

sts(bool b) { return b ? "true" : "false"; }

sts(char c) { return string(1, c); }

sts(const char* s) { return (string) s; }

template<class A, class B>
sts(pair<A, B>);

template<class T>
sts(T v) {
    string s = "{", sep = "";
    for (auto x: v) {
        s += sep;
        sep = ", ";
        s += ts(x);
    }
    return s + "}";
}

template<class A, class B>
sts(pair<A, B> p) { return "(" + ts(p.first) + ", " + ts(p.second) + ")"; }

void dbgPrint() { cerr << endl; }

template<class A, class... B>
void dbgPrint(A a, B... b) {
    cerr << ' ' << ts(a);
    dbgPrint(b...);
}

#ifdef LOCAL
#define dbg(...) cerr << "line #" << __LINE__ << " [" << #__VA_ARGS__ << "]:", dbgPrint(__VA_ARGS__)
#else
#define dbg(...)
#endif

#define len(a) (int) (a).size()
#define all(a) (a).begin(), (a).end()
#define pb push_back
#define eb emplace_back
#define rep(x, y, a) for (int x = (y); x < (int)(a); ++x)
#define asd(n) rep(i, 0, n)
#define jkl(n) rep(j, 0, n)
#define UB upper_bound
#define LB lower_bound
#define mp make_pair


template<class A, class B>
inline int chkmax(A& a, B b) {
    if (a < (A) b) {
        a = (A) b;
        return 1;
    }
    return 0;
}

template<class A, class B>
inline int chkmin(A& a, B b) {
    if (a > (A) b) {
        a = (A) b;
        return 1;
    }
    return 0;
}

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

void solve();

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.precision(41);
    int q = 1;
    // cin >> q;
    while (q--) solve();
}
const int M = 998244353;
void add(int &a, int b) {
    a += b;
    if (a >= M) a -= M;
}
const int N = 5e7 + 2;
ll fact[N];
ll ifact[N];

int bp(int a, int b) {
    if (b == 0) return 1;
    if (b % 2) return ll(a) * bp(a, b - 1) % M;
    return bp(ll(a) * a % M, b / 2);
}
int nck(int n, int k) {
    if (k > n) return 0;
    if (k < 0) return 0;
    return fact[n] * ifact[k] % M * ifact[n - k] % M;
}
void solve() {
    fact[0] = 1;
    asd(N - 1) fact[i + 1] = ll(i + 1) * fact[i] % M;
    ifact[N - 1] = bp(fact[N - 1], M - 2);
    dbg(ifact[N - 1]);
    for (int i = N - 2; i >= 0; --i) {
        ifact[i] = ifact[i + 1] * (i + 1) % M;
    }
    int n, c;
    cin >> n >> c;
    vvi dp(21, vi(c + 1));
    rep(i, 1, c + 1) dp[1][i] = 1;
    vvi divs(c + 1);
    rep(i, 1, c + 1) {
        for (int j = i * 2; j <= c; j += i) divs[j].eb(i);
    }
    rep(i, 2, 21) {
        rep(j, 1, c + 1) {
            for (int k : divs[j]) {
                add(dp[i][j], dp[i - 1][k]);
            }
        }
    }
    dbg(dp);
    int ans = 0;
    rep(path, 1, dp.size()) rep(st, 1, c + 1) {
        add(ans, ll(dp[path][st]) * nck(n - 1, path - 1) % M);
    }
    put(ans);
    return;
}
