#include <bits/stdc++.h>
#define rep(i, n) for(int i = 0; i < (int)(n); i ++)
#define rep1(i, n) for(int i = 1; i <= (int)(n); i ++)
#define MP make_pair

using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int MOD = 998244353;

int fac[2000005], ifac[2000005];

void gen_fac()
{
	fac[0] = 1;
	rep1(i, 2000000) fac[i] = 1LL * fac[i - 1] * i % MOD;
	ifac[1] = 1;
	for(int i = 2; i <= 2000000; i ++) ifac[i] = MOD - 1LL * ifac[MOD % i] * (MOD / i) % MOD;
	ifac[0] = 1;
	rep1(i, 2000000) ifac[i] = 1LL * ifac[i - 1] * ifac[i] % MOD;
}

int comb(int n, int m)
{
	if(n < m) return 0;
	return 1LL * fac[n] * ifac[n - m] % MOD * ifac[m] % MOD;
}

int solve(int n, int m, int k)
{
	int tot = comb((3 * m - k) / 2 + n - 1, n - 1);
	tot = (tot - 1LL * k * comb((m - k) / 2 + n - 1, n - 1) % MOD + MOD) % MOD;
	tot = (tot - 1LL * (n - k) * comb((m - k - 2) / 2 + n - 1, n - 1) % MOD + MOD) % MOD;
	return tot;
}

int main()
{
	gen_fac();
	int n, m;
	scanf("%d%d", &n, &m);
	int ans = 0;
	for(int i = 0; i <= m; i ++)
	if(!(m - i & 1)) ans = (ans + 1LL * comb(n, i) * solve(n, m, i)) % MOD;
	printf("%d\n", ans);
	return 0;
}
//#include <bits/stdc++.h>
#include "bits/stdc++.h"
using namespace std;
typedef long long ll;
//#include "boost/multiprecision/cpp_int.hpp"
//typedef boost::multiprecision::cpp_int ll;
typedef long double dd;
//#define i_7 (ll)(1E9+7)
#define i_7 998244353
#define i_5 i_7-2

ll mod(ll a){
    ll c=a%i_7;
    if(c>=0)return c;
    return c+i_7;
}
typedef pair<ll,ll> l_l;
typedef pair<dd,dd> d_d;
ll inf=(ll)1E16;
#define rep(i,l,r) for(ll i=l;i<=r;i++)
#define pb push_back
ll max(ll a,ll b){if(a<b)return b;else return a;}
ll min(ll a,ll b){if(a>b)return b;else return a;}
void Max(ll &pos,ll val){pos=max(pos,val);}//Max(dp[n],dp[n-1]);
void Min(ll &pos,ll val){pos=min(pos,val);}
void Add(ll &pos,ll val){pos=mod(pos+val);}
dd EPS=1E-9;
#define fastio ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define fi first
#define se second
#define endl "\n"
#define SORT(x) sort(x.begin(),x.end())
#define ERASE(x) x.erase(unique(x.begin(),x.end()),x.end())
#define POSL(x,v) (lower_bound(x.begin(),x.end(),v)-x.begin())
#define POSU(x,v) (upper_bound(x.begin(),x.end(),v)-x.begin())
//template<class T>void max(T a,T b){if(a<b)return b;else return a;}
//template<class T>void min(T a,T b){if(a>b)return b;else return a;}
//template<class T>bool Max(T&a, T b){if(a < b){a = b;return 1;}return 0;}
//template<class T>bool Min(T&a, T b){if(a > b){a = b;return 1;}return 0;}

//////////////////////////


ll po(ll i,ll p){
    if(p==0)return 1;
    else{
        i=mod(i);
        if(p==1)return i;
        if(p%2==0)return po(mod(i*i),p/2);
        return mod(i*po(i,p-1));
    }
}
ll bunbo(ll n){
    return po(n,i_5);
}


#define N 6000004
ll kai[N];
ll kai2[N];
void calc(){
    kai[0]=1;
    kai2[0]=1;
    rep(i,1,N-1){
        kai[i]=mod(kai[i-1]*i);
    }
    kai2[N-1]=po(kai[N-1],i_5);
    for(ll i=N-2;i>=0;i--){
        kai2[i]=mod(kai2[i+1]*(i+1));
    }
}
ll comb(ll n,ll k){
    if(n<k)return 0;
    if(n==0)return 1;
    return mod(mod(kai[n]*kai2[n-k])*kai2[k]);
}

int main(){fastio
    calc();
    ll n,m;cin>>n>>m;
    ll a1,a2=0,a3=0;
    a1=comb(3*m+n-1,n-1);
    rep(ma,2*m+1,3*m){
        ll res=3*m-ma;
        Add(a2,comb(res+n-2,n-2));
    }
    a2=mod(a2*n);
    rep(i,m+1,3*m){
        if((3*m-i)%2==1)continue;
        if(n<i)continue;
        ll res=(3*m-i)/2;
        Add(a3,comb(n,i)*comb(res+n-1,n-1));
    }
    cout<<mod(a1-a2-a3)<<endl;
    return 0;
}
