#include <bits/stdc++.h>
#define PB push_back
#define SZ(a) ((int)(a).size())
#define LL long long
#define X first
#define ll long long
#define Y second
using namespace std;
const int INF = 1000 * 1000 * 1000;
const LL LINF = INF * (LL)INF;
const int mod = 998244353;


const int MOD = 998244353;
const int MAXN = 1e6 + 10;
const int A = 26;
int fact[2500005];
int w[5000001];;
int inv[2500005];
int R[2000001];
int t1[2000001],t2[2000001];
typedef vector<int> poly;
const int P = 998244353;
int mult(int a , int b)
{
	return a * (LL)b % mod;
}
int add(int a , int b)
{
	return a + b >= mod ? a + b - mod : a + b;
}
int sub(int a , int b)
{
	return a - b < 0 ? a - b + mod : a - b;
}
int c(int n , int k)
{
	if(n < k)
		return 1;
	return mult(fact[n] , mult(inv[k] , inv[n - k]));
}
int modPow(int a , int step)
{
	int ans = 1;
	while(step)
	{
		if(step & 1)
			ans = mult(ans , a);
		step >>= 1;
		a = mult(a , a);
	}
	return ans;
}
int lim;
namespace fft {
 
	const int mod = 998244353;
	const int root = 15311432;
	const int root_1 = 469870224;
	const int root_pw = 1 << 23;
 
	template<class T>
	T eea(T a, T b, T& x, T& y) {
		if (!b) {
			x = 1;
			y = 0;
			return a;
		}
	
		T x1, y1;
		T g = eea(b, a % b, x1, y1);
		x = y1;
		y = x1 - (a / b) * y1;
		return g;
	}
 
	int inverse(int n) {
		int x, y;
		eea(n, mod, x, y);
		x %= mod;
		if (x < 0)
			x += mod;
		return x;
	}
 
	void fft(vector<int>& a, bool invert) {
		int n = a.size();
 
		for (int i = 1, j = 0; i < n; i++) {
			int bit = n >> 1;
			for (; j & bit; bit >>= 1)
				j ^= bit;
			j ^= bit;
 
			if (i < j)
				swap(a[i], a[j]);
		}
 
		for (int len = 2; len <= n; len <<= 1) {
			int wlen = invert ? root_1 : root;
			for (int i = len; i < root_pw; i <<= 1)
				wlen = 1LL * wlen * wlen % mod;
 
			for (int i = 0; i < n; i += len) {
				int w = 1;
				for (int j = 0; j < len / 2; j++) {
					int u = a[i+j], v = (int)(1LL * a[i+j+len/2] * w % mod);
					a[i+j] = u + v < mod ? u + v : u + v - mod;
					a[i+j+len/2] = u - v >= 0 ? u - v : u - v + mod;
					w = 1LL * w * wlen % mod;
				}
			}
		}
 
		if (invert) {
			int n_1 = inverse(n);
			for (int& x : a)
				x = 1LL * x * n_1 % mod;
		}
	}
}
 
int pm(int x) {
	if (x < fft::mod - x) {
		return x;
	} else {
		return x - fft::mod;
	}
}
 
const int FIELD = 131072;
 
vector<int> poly_mul(vector<int> a, vector<int> b) {
	int n = a.size() + b.size() - 1;
	int m = 1;
	while (m < n)
		m *= 2;
	a.resize(m);
	b.resize(m);
 
	if (a == b) {
		fft::fft(a, false);
		b = a;
	} else {
		fft::fft(a, false);
		fft::fft(b, false);
	}
	for (int i=0; i<m; i++)
		a[i] = a[i] * 1ll * b[i] % fft::mod;
	fft::fft(a, true);
	a.resize(n);
	return a;
}
inline int count(int n, int m)
{
	return c(n - 1 + m, m);
}
 
int jebu(int n, int odd, int m)
{
	return count(n, (3 * m - odd) / 2);
}

 
 
int dp[100][200];
int main()
{
	ios_base::sync_with_stdio(0);
	
	fact[0] = inv[0] = 1;
	for(int i = 1; i <= 2500000; i++)
	{
		fact[i] = mult(fact[i - 1] , i);
		inv[i] = modPow(fact[i] , mod - 2);
	}
	int n , m;
	cin >> n >> m;
	
	int ans = c(n + 3 * m - 1 , n - 1);
	ans = sub(ans , c(m - 1 + n - 1 , m - 1));
	n--;m--;
	vector<int> a(n + 1) , b(m + 1);
	for(int i = 1; i <= n; i++)
		a[i] = mult(inv[i - 1] , inv[n - i]);
	for(int i = 0; i <= m; i++)
		b[i] = mult(inv[m - i] , inv[i]);
	vector<int> C = poly_mul(a , b);
	LL ans2 = ans;
	for(int j = 1; j < C.size(); j++)
	{
		ans = sub(ans , mult(C[j] , mult(fact[j - 1] , fact[n + m - j])));
	}
	n++;
	m++;
	/*int odd = 0;
	for(int cnt = m + 2; cnt <= n && cnt <= 3 * m; cnt += 2)
	{
		int coef = c(n, cnt);
		int here = jebu(n, cnt, m);	
		odd = add(odd, mult(coef, here));
	}*/
	//ans = sub(ans , odd);
	
	for(int j = m + 1; j <= 3 * m; j ++)
	{
		if(j <= n && (3 * m - j) % 2 == 0)
		{
			
			int zalupa1 = mult(c(n , j) , c(n + (3 * m - j) / 2 - 1 , n - 1));
			ans = sub(ans , zalupa1);
		}
			
	}
	
	
	/*for(int i = 1; i < n; i++)
		for(int j = 0; j < m; j++)
		{
			//if(i == 0 && j)
				//continue;
			//cerr << i << " " << j << " " << mult(c(i - 1 + j , i - 1) , c(n - 1 - i + m - 1 - j , m - 1 - j)) << endl;
			ans2 = sub(ans2 , mult(c(i - 1 + j , i - 1) , c(n - 1 - i + m - 1 - j , m - 1 - j)));
		}*/
	/*dp[0][0] = 1;
	for(int i = 0; i < n; i++)
	{
		for(int j = 0; j <= 3 * m; j++)
		{
			for(int k = 0; k <= 2 * m; k++)
			{
				dp[i + 1][j + k] = add(dp[i][j] , dp[i + 1][j + k]);
			}
		}
	}*/
				
	cout << ans;
}


Measured memory_bytes: 48188