#include<bits/stdc++.h>
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
using namespace std;
inline int read(){
	int res=0;
	bool zf=0;
	char c;
	while(((c=getchar())<'0'||c>'9')&&c!='-');
	if(c=='-')zf=1;
	else res=c-'0';
	while((c=getchar())>='0'&&c<='9')res=(res<<3)+(res<<1)+c-'0';
	if(zf)return -res;
	return res;
}
const int maxn=2e5+5,P=998244353;
int f[maxn],g[maxn];
int p[maxn],r;
int v[maxn],inv[25];
signed main(){
	int n=read(),m=read(),ans=1;
	inv[1]=1;
	for(register int i=2;i<=20;++i){
		inv[i]=1ll*inv[P%i]*(P-P/i)%P;
	}
	for(register int i=2,t;i<=m;++i){
		if(!v[i]){
			f[i]=n,g[i]=1,p[++r]=i;
		}
		for(register int j=1;j<=r&&(t=i*p[j])<=m;++j){
			v[t]=1;
			if(i%p[j]){
				f[t]=1ll*f[i]*n%P,g[t]=1;
			}
			else{
				f[t]=1ll*f[i]*(n+g[i])%P*inv[g[i]+1]%P,g[t]=g[i]+1;
				break;
			}
		}
		ans+=f[i];
		(ans>=P)&&(ans-=P);
	}
	printf("%d\n",ans);
	return 0;
}
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const ll MOD = 998244353;
ll factorial[400005];
ll inverse[400005];
map<ll, ll> choosepre;

ll modpow(ll a, ll b) {
	if(b == 0) return 1 % MOD;
	ll half = modpow(a, b/2);
	ll res = half * half;
	res %= MOD;
	if(b % 2 == 1) {
		res *= a;
		res %= MOD;
	}
	return res;
}

ll choose(ll n, ll k) {
	// n! / k!(n-k)!
	// n * (n - 1) * (n - 2) * ... * (n - k + 1)
	ll ans = 1;
	for(int i = 0; i < k; i++) {
		ans *= (n - i);
		ans %= MOD;
	}
	ans *= inverse[k]; // inverse
	ans %= MOD;
	return ans;
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	
	factorial[0] = 1;
	inverse[0] = 1;
	for(int i = 1; i < 400005; i++) {
		factorial[i] = factorial[i - 1] * i;
		factorial[i] %= MOD;
		inverse[i] = modpow(factorial[i], MOD - 2);
	}
	
	int N, M; cin >> N >> M;
	ll ans = 1;
	
	// huge overhead for choosing so precompute!!!!!!!
	for(int i = 0; i < 18; i++) {
		choosepre[i + N - 1] = choose(i + N - 1, N - 1);
	}
	
	for(int i = 2; i <= M; i++) {
		int num = i;
		ll expo_count = 0;
		ll curr_count = 1;
		double up = log(i) / log(2);
		ll l = 0, r = ceil(up), mid;
		while(l <= r) {
			mid = (l + r) / 2;
			ll power = modpow(2, mid);
			if(num % power == 0) {
				expo_count = max(expo_count, mid);
				l = mid + 1;
			}
			else {
				r = mid - 1;
			}
		}
		num /= modpow(2, expo_count);
		curr_count *= choosepre[expo_count + N - 1];
		curr_count %= MOD;
		
		for(int j = 3; j * j <= i; j += 2) {
			if(num % j == 0) {
				expo_count = 0;
				up = log(i) / log(j);
				l = 0, r = ceil(up);
				while(l <= r) {
					mid = (l + r) / 2;
					ll power = modpow(j, mid);
					if(num % power == 0) {
						expo_count = max(expo_count, mid);
						l = mid + 1;
					}
					else {
						r = mid - 1;
					}
				}
				curr_count *= choosepre[expo_count + N - 1];
				curr_count %= MOD;
				num /= modpow(j, expo_count);
			}
			//cout << i << ' ' << expo_count << '\n';
		}
		if(num > 2) { // still prime factor
			expo_count = 1;
			curr_count *= choosepre[expo_count + N - 1];
			curr_count %= MOD;
		}		
		ans += curr_count;
		ans %= MOD;
	}
	cout << ans << '\n';
}
