#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma GCC optimize("unroll-loops")
#pragma warning(disable : 4996)
#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<math.h>
#include<iomanip>
#include<set>
#include<numeric>
#include<cstring>
#include<cstdio>
#include<functional>
#include<bitset>
#include<limits.h>
#include<cassert>
#include<iterator>
#include<complex>
#include<stack>
#include<unordered_map>
#include<unordered_set>
#include<time.h>
#include<random>
#include<array>


using namespace std;

#define REP(i, n) for(int i = 0;i < n;++i)
#define REPR(i, n) for(int i = n-1;i >= 0;--i)
#define FOR(i, m, n) for(int i = m;i < n;++i)
#define FORR(i, m, n) for(int i = m-1;i >= n;--i)
#define SORT(v, n) sort(v, v+n);
#define VSORT(v) sort(v.begin(), v.end());
#define REVERSE(v,n) reverse(v,v+n);
#define VREVERSE(v) reverse(v.begin(), v.end())
#define ll long long
#define print(x) cout<<(x)<<'\n'
#define pe(x) cout<<(x)<<" "
#define DEBUG(x) cout<<#x<<": "<<x<<endl
#define lb(v,n) lower_bound(v.begin(), v.end(), (n))
#define ub(v,n) upper_bound(v.begin(), v.end(), (n))
#define int long long
//#define double long double
#define all(x) (x).begin(), (x).end()
#define print_space(v) REP(i,v.size())cout << v[i] << ((i == v.size() - 1) ? "\n" : " ")
template<typename T1, typename T2> inline void chmin(T1 & a, T2 b) { if (a > b) a = b; }
template<typename T1, typename T2> inline void chmax(T1& a, T2 b) { if (a < b) a = b; }
typedef pair<int, int>P;
typedef array<int, 3> arr3;
std::random_device rd;
std::mt19937 mt(rd());
constexpr int MOD = 998244353; constexpr int MAX = 2000020;
const double pi = acos(-1); constexpr double EPS = 1e-8;
constexpr ll INF = 1e18;

long long fac[MAX], finv[MAX], inv[MAX];

// テーブルを作る前処理
void COMinit() {
	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;
	}
}

// 二項係数計算
long long COM(int n, int k) {
	if (n < k) return 0;
	if (n < 0 || k < 0) return 0;
	return fac[n] * (finv[k] * finv[n - k] % MOD) % MOD;
}
ll add(ll x, ll y) {
	x += y;
	if (x >= MOD) return x - MOD;
	return x;
}
ll sub(ll x, ll y) {
	x -= y;
	if (x < 0) return x + MOD;
	return x;
}
ll mult(ll x, ll y) {
	return (x * y) % MOD;
}
ll bin_pow(ll x, ll p) {
	if (p == 0) return 1;
	if (p & 1) return mult(x, bin_pow(x, p - 1));
	return bin_pow(mult(x, x), p / 2);
}


void solve() {
	int N, M; cin >> N >> M;
	ll ans = 0;
	COMinit();
	REP(k, min(N+1,M + 1)) {
		if (M % 2 != k%2)continue;
		int tmp = COM(N, k);
		int c = (3 * M - k) / 2;
		tmp = mult(tmp, mult(finv[c],mult(finv[N-1],fac[c + N - 1])));

		int c2 = (M - k) / 2;
		int sb1 = mult(mult(COM(N,k),k), mult(fac[c2 + N - 1], mult(finv[c2], finv[N - 1])));
		int c3 = (M - k - 2) / 2;
		if (c3 >= 0) {
			int sb2 = mult(mult(COM(N,k),N - k), mult(fac[c3 + N - 1], mult(finv[c3], finv[N - 1])));
			tmp = sub(tmp, sb2);
		}
		tmp = sub(tmp, sb1);
		ans = add(ans, tmp);
	}
	print(ans);
}

signed main() {
	cin.tie(0);
	ios::sync_with_stdio(false);
	//int q; cin >> q;
	//while (q--)
	solve();
}


#include <bits/stdc++.h>
using i64 = long long;

long long *fact, *inv;

template <typename T, typename U, typename V>
auto pow(T x_, U n_, V mod_) {
    using R = std::common_type_t<T, U, V>;
    R ret = 1, x = x_, n = n_, mod = mod_;
    while(n > 0) {
        if ((n & 1) == 1) ret = (ret * x) % mod;
        x = (x * x) % mod;
        n >>= 1;
    }
    return ret;
}

template <typename T, typename U>
auto inverse(T x, U p) { return pow(x, p - 2, p); }

void init_factorial(int n, long long mod) {
    fact = new long long[n + 1];
    inv = new long long[n + 1];
    fact[0] = 1;
    for (long long i = 1; i <= n; i++) fact[i] = fact[i - 1] * i % mod;
    inv[n] = inverse(fact[n], mod);
    for (long long i = n; i > 0; i--) inv[i - 1] = inv[i] * i % mod;
}

int main() {
    constexpr i64 mod = 998244353;
    int n, m;
    std::cin >> n >> m;
    init_factorial(n + 3 * m, mod);

    i64 ret = 0;
    for (int i = 0; i <= std::min(n, m); i++) {
        int r = 3 * m - i;
        if (r & 1) continue;
        r >>= 1;
        i64 t = fact[r + n - 1] * inv[n - 1] % mod * inv[r] % mod;
        ret = (ret + t * fact[n] % mod * inv[i] % mod * inv[n - i] % mod) % mod;
    }

    for (int i = 0; i <= std::min(n, m); i++) {
        int r = m - i;
        if (r & 1) continue;
        r >>= 1;
        i64 t = fact[r + n - 1] * inv[n - 1] % mod * inv[r] % mod;
        ret = (ret + mod - t * fact[n] % mod * inv[i] % mod * inv[n - i] % mod * n % mod) % mod;
    }

    for (int i = 0; i <= std::min(n - 1, m); i++) {
        int r = m - i;
        if (r & 1) continue;
        r >>= 1;
        i64 t = fact[r + n - 2] * inv[n - 2] % mod * inv[r] % mod;
        ret = (ret + t * fact[n - 1] % mod * inv[i] % mod * inv[n - i - 1] % mod * n % mod) % mod;
    }

    std::cout << ret << std::endl;

    return 0;
}
