#include <bits/stdc++.h>
using namespace std;
using ll=long long;using vl=vector<ll>;
using vi=vector<int>;using vs=vector<string>;using vc=vector<char>;
using vvl=vector<vl>;using pl=pair<ll,ll>;using vvc=vector<vc>;
using vd=vector<double>;using vpl=vector<pl>;using vb=vector<bool>;
#define rep(i,r) for(ll i=0;i<(r);i++)
#define Rep(i,l,r) for(ll i=(l);i<(r);i++)
#define print(n) cout<<(n)<<endl
#define all(a)  (a).begin(),(a).end()
#define sortp(d) sort(all(d))
#define sortm(d) sort(d.rbegin(),d.rend())
//cout<<fixed<<setprecision(15)<<
//priority_queue<pl,vpl,greater<pl>>
void yn(bool b){print(b?"Yes":"No");exit(0);}
ll gcd(ll a,ll b) {if(b==0)return a;else return gcd(b,a%b);}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
ll modpow(ll a,ll n,ll mod) {ll res=1;while(n>0)
{if(n&1)res=res*a%mod;a=a*a%mod;n >>= 1;}return res;}
ll modinv(ll a,ll mod){return modpow(a, mod - 2, mod);}
ll p=0,q=0,r=0,inf=100000000000000000,mod=1000000007;
ll dx[8]={1,0,-1,0,1,-1,-1,1},dy[8]={0,1,0,-1,1,1,-1,-1};
//ここから本質←ほんまか？
double pi=3.141592653589793238462643383279;
ll fac[10000001],inv[10000001],facinv[10000001];
void cominit(ll max){fac[0]=1;fac[1]=1;inv[1]=1;facinv[0]=1;facinv[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;facinv[i]=facinv[i-1]*inv[i]%mod;}}
ll com(ll n,ll k){return fac[n]*(facinv[k]*facinv[n-k]%mod)%mod;}
int main()
{
  ll z,m;cin>>z>>m;
  mod=998244353;
  cominit(z+m);
  Rep(i,1,m+1)
  {
    ll n=i;
    q=1;
    for(ll div=2;div*div<=n;div++)
    {
        if(n%div!=0)continue;
        ll tmp=0;
        while(n%div==0)n/=div,tmp++;
        //div^tmpが素因数
        /*any*/
      	q*=com(z+tmp-1,tmp);
      	q%=mod;
    }
    if(n!=1){/*any*/q*=z;q%=mod;}
    p+=q;
    p%=mod;
  }
  print(p);
}
//中１水コーダーになりたいんです...お願いします...後輩にカッコつけたいんです...マジで...
//てかもう中１終わるの流石にバグだろ
//↑それな
//劇団ひとり定期
//さみし()
//そういえばコーヒーは美味しいですね。魔剤なんか飲むなら黙ってコーヒー
//コメントの使い方ってこういう感じですよね！？
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <vector>
#define setIO(x) freopen(x".in", "r", stdin), freopen(x".out", "w", stdout)
#define closefile fclose(stdin), fclose(stdout)
#define m_p make_pair
#define sz(x) (int)x.size()
#define see(x) cerr << x << " "
#define seeln(x) cerr << x << endl
#define out(x) cerr << #x << " = " << x << " "
#define outln(x) cerr << #x << " = " << x << endl
#define outarr(x, l, r) {cerr<< #x"[" << l << " ~ " << r << "] = "; for (int _i = l; _i <= r; ++_i) cerr << x[_i] << " "; cerr << endl;}
using namespace std;
typedef long long ll;
typedef pair <int, int> pii;
#define gc() getchar()
//#define gc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
char buf[1 << 21], *p1 = buf, *p2 = buf;
template <class T> void read(T &x)
{
    x = 0; int c = gc(); int flag = 0;
    while (c < '0' || c > '9') flag |= (c == '-'), c = gc();
    while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) +(c ^ 48), c = gc();
    if (flag) x = -x;
}
template <class T> T _max(T a, T b){return b < a ? a : b;}
template <class T> T _min(T a, T b){return a < b ? a : b;}
template <class T> bool checkmax(T &a, T b){return a < b ? a = b, 1 : 0;}
template <class T> bool checkmin(T &a, T b){return b < a ? a = b, 1 : 0;}
const int N = 200005, mod = 998244353;
void add(int &a, int b){a += b; (a >= mod) && (a -= mod);}
void sub(int &a, int b){a -= b; (a < 0) && (a += mod);}
void mul(int &a, int b){a = (ll)a * b % mod;}
int Add(int a, int b){a += b; return a >= mod ? a - mod : a;}
int Sub(int a, int b){a -= b; return a < 0 ? a + mod : a;}
int Mul(int a, int b){return (ll)a * b % mod;}
int qpow(int a, int b){int ans = 1; while (b) {if (b & 1) ans = (ll)ans * a % mod; a = (ll)a * a % mod; b >>= 1;} return ans;}
vector<int> f[N];
int n, m, lim;
int ans = 0;
int fac[N], ifac[N];
void init()
{
	read(n); read(m);
	for (int i = 1; i <= m; ++i) for (int j = i; j <= m; j += i) if (i > 1) f[j].push_back(i);
	fac[0] = 1; for (int i = 1; i <= n; ++i) fac[i] = Mul(fac[i - 1], i);
	ifac[n] = qpow(fac[n], mod - 2); for (int i = n - 1; i >= 0; --i) ifac[i] = Mul(ifac[i + 1], i + 1);
}

const int K = 448;
int cnt = 0;
void dfs(int x, int s, int co, int num)
{
	if (m < (ll)x * s) x = K + 1;
	if (x > K)
	{
		add(ans, Mul(fac[n], Mul(ifac[n - num], co)));
		if (K + 1 <= m / s && num < n)
		{
			int pq = m / s - K;
			add(ans, Mul(Mul(fac[n], pq), Mul(ifac[n - 1 - num], co)));
		}
		return;
	}
	int now = s, lim = m / x;
	for (int i = 0; i <= n - num; ++i)
	{
		dfs(x + 1, now, Mul(co, ifac[i]), num + i); 
		if (now > lim) break;
		now *= x;
	}
}

void solve()
{
	dfs(2, 1, 1, 0);
	outln(cnt);
	printf("%d\n", ans);
}

int main()
{
	init();
	solve();
    return 0;
}
