#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

#define rep(i, n) for(int i=0, i##_len=(n); i<i##_len; ++i)
#define ALL(x) (x).begin(), (x).end()
#define SZ(x) ((int)(x).size())
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return 1; } return 0; }

#ifdef LOCAL
    #define eprintf(...) fprintf(stderr, __VA_ARGS__)
#else
    #define eprintf(...) do{}while(0)
#endif




const int MAX = 1800000;
const ll MOD = 998244353;

struct Comb {
	vector<ll> fac, finv, inv; // 階乗、階乗の逆数、逆数
	
	Comb(int n = MAX) : fac(n), finv(n), inv(n){
		fac[0] = fac[1] = 1;
		finv[0] = finv[1] = 1;
		inv[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;
			finv[i] = finv[i - 1] * inv[i] % MOD;
		}
	}
	
	ll C( ll n, ll k ){
		if (n < k) return 0;
		if (n < 0 || k < 0) return 0;
		return fac[n] * (finv[k] * finv[n - k] % MOD) % MOD;
	}
	
	ll P( ll n, ll k ){
		if (n < k) return 0;
		if (n < 0 || k < 0) return 0;
		return fac[n] * finv[n-k] % MOD;
	}
};


template <std::uint_fast64_t Modulus> class modint {
	using u64 = std::uint_fast64_t;

public:
	u64 a;

	constexpr modint(const u64 x = 0) noexcept : a(x % Modulus) {}
	constexpr u64 &value() noexcept { return a; }
	constexpr const u64 &value() const noexcept { return a; }
	constexpr modint operator+(const modint rhs) const noexcept {
		return modint(*this) += rhs;
	}
	constexpr modint operator-(const modint rhs) const noexcept {
		return modint(*this) -= rhs;
	}
	constexpr modint operator*(const modint rhs) const noexcept {
		return modint(*this) *= rhs;
	}
	constexpr modint operator/(const modint rhs) const noexcept {
		return modint(*this) /= rhs;
	}
	constexpr modint &operator+=(const modint rhs) noexcept {
		a += rhs.a;
		if (a >= Modulus) {
			a -= Modulus;
		}
		return *this;
	}
	constexpr modint &operator-=(const modint rhs) noexcept {
		if (a < rhs.a) {
			a += Modulus;
		}
		a -= rhs.a;
		return *this;
	}
	constexpr modint &operator*=(const modint rhs) noexcept {
		a = a * rhs.a % Modulus;
		return *this;
	}
	
	// rhsの(MOD-2)乗を掛ける
	constexpr modint &operator/=(modint rhs) noexcept {
		u64 exp = Modulus - 2;
		while (exp) {
			if (exp % 2) {
				*this *= rhs;
			}
			rhs *= rhs;
			exp /= 2;
		}
		return *this;
	}
	
	friend ostream &operator<<(ostream &s,const modint &rhs) noexcept {
		return s << rhs.a;
	}
	
	modint pow(ll y) noexcept {
		modint result(1);
		modint x(a);
		
		while ( y ){
			if ( y & 1 )
				result *= x;
			x *= x;
			y >>= 1;
		}
		return result;
	}
};

using mint = modint<MOD>;




/*
	2のブロックをA個、1のブロックをB個、
	A*2+B = M*3

	2のブロックは1か所に最大M個まで置ける
	  2のブロックを1箇所にM個置くと、そこには1のブロックを置けない
	
	1のブロックは1か所に最大1個まで置ける
*/

ll n, m;

int main(){
	cin >> n >> m;
	Comb c;
	
	ll m3 = m*3;
	mint result = 0;
	for ( ll a = m; a*2 <= m*3; a++ ){
		ll b = m*3 - a*2;
		mint nCb = c.C(n,b); // 1のブロックを置くパターン数。
		mint n1Cb = c.C(n-1,b);
		
		// a個の2のブロックをn箇所に自由に置くパターン数
		mint ap = c.C(n-1+a,a);
		
		/* 2のブロックを1か所にM個、残りのn-1箇所にa-M個置くパターン
		    = n * nCr(n-2+a-M,a-M)
		*/
		mint am1 = c.C(n-2+a-m,a-m); am1 *= n;
		
		/* 2のブロックを1か所にk個、残りのn-1箇所にa-k個置くパターン(M+1 <= k <= a) (a-M-1 >= a-k >= 0)
		   n * Σ nCr(n-2+a-k,a-k)
		    = n * nCr(n-2+(a-M-1)+1,(a-M-1))
		*/
		mint am = c.C(n-2+a-m,a-m-1); am *= n;
		
		//eprintf( "a=%lld b=%lld / ncb=%lld ap=%lld / am1=%lld ncb=%lld n1cb=%lld / am=%lld ncb=%lld\n", a, b, nCb, ap, am1, nCb, n1Cb, am, nCb );
		result +=  nCb*ap - am1*nCb + am1*n1Cb - am*nCb;
	}
	
	cout << result << endl;
	
	
	return 0;
}




Measured memory_bytes: 45460