#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")

#include <iostream>
#include <vector>

using namespace std;

using ll = long long;

const ll MOD = 998244353;

const int MAX_C = 50'000'000;

ll bin_pow(ll a, ll n) {
	ll res = 1;
	while (n) {
		if (n & 1) {
			res = res * a % MOD;
		}
		a = a * a % MOD;
		n >>= 1;
	}
	return res;
}

ll inv(ll x) {
	return bin_pow(x, MOD - 2);
}

ll cnk(ll n, ll k) {
	if (n < 0 || k < 0 || n - k < 0) {
		return 0;
	}
	ll res = 1;
	for (ll i = n - k + 1; i <= n; ++i) {
		res = res * i % MOD;
	}
	ll res2 = 1;
	for (ll i = 1; i <= k; ++i) {
		res2 = res2 * i % MOD;
	}
	return res * inv(res2) % MOD;
}

int sol(ll n, ll k) {
	return cnk(n + k - 1, k);
}

int min_div_val[3 * MAX_C + 10];

int pr_sz = 0;
int pr[MAX_C / 10];

int main() {
	int C1;
	int n, C;
	cin >> n >> C1;
	C = MAX_C;
	for (int i = 1; i <= C; ++i) {
		min_div_val[i] = 0;
	}
	for (int i = 1; i < MAX_C / 10; ++i) {
		pr[i] = MAX_C;
	}
	vector<int> calc(30);
	for (int i = 1; i <= 29; ++i) {
		calc[i] = sol(n, i);
	}
	ll res = 1;
	for (int i = 2; i <= C1; ++i) {
		if (!min_div_val[3 * i]) {
			min_div_val[3 * i] = i;     // lp
			min_div_val[3 * i + 1] = 1; // pow
			min_div_val[3 * i + 2] = 1; // prev_ans
			pr[pr_sz++] = i;
		}
		ll ans_here = min_div_val[3 * i + 2] * 1ll * calc[min_div_val[3 * i + 1]] % MOD;
		res += ans_here;
		for (int j = 0; pr[j] <= min_div_val[3 * i] && pr[j] * i <= C; ++j) {
			int new_val = pr[j] * i;
			min_div_val[3 * new_val] = pr[j];
			if (pr[j] == min_div_val[3 * i]) {
				min_div_val[3 * new_val + 1] = min_div_val[3 * i + 1] + 1;
				min_div_val[3 * new_val + 2] = min_div_val[3 * i + 2];
			} else {
				min_div_val[3 * new_val + 1] = 1;
				min_div_val[3 * new_val + 2] = ans_here;
			}
		}
	}
	res %= MOD;
	cout << (res + MOD) % MOD;
	return 0;
}
