#include<iostream>
#include<cassert>
#include<stdexcept>
#include<utility>
#include<functional>
#include<numeric>
#include<cmath>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<array>
#include<stack>
#include<queue>
#include<deque>
#include<vector>
#include<complex>
#include<set>
#include<map>
#include<unordered_map>
#include<unordered_set>
#include<string>
#include<bitset>
using namespace std;
using ll=long long;




namespace ProconLib{
    using ll=long long;
    using Int=int;
    template<Int MOD,bool IsPrime=true>
    class ModInt{
        Int n;        
        static Int regularize(int n){Int tmp=n%MOD; return tmp>=0 ? tmp : tmp+MOD;}
        static Int regularize(ll n){Int tmp=n%MOD; return tmp>=0 ? tmp : tmp+MOD;}
        public:
        ModInt():n(0){};
        ModInt(int n):n(regularize(n)){}
        ModInt(long long n):n(regularize(n)){}
        ModInt(const ModInt<MOD,IsPrime> &mn):n(mn.n){}
        explicit operator int() const{return n;}
        explicit operator long long() const{return n;}

        ModInt<MOD,IsPrime>& operator+=(ModInt<MOD,IsPrime> rhs);
        ModInt<MOD,IsPrime>& operator-=(ModInt<MOD,IsPrime> rhs);
        ModInt<MOD,IsPrime>& operator*=(ModInt<MOD,IsPrime> rhs);

        bool operator==(ModInt<MOD,IsPrime> rhs){return n==rhs.n;}
        const Int& get() const {return n;}
        void set(int x){n=regularize(x);}
        void set(ll x){n=regularize(x);}        
    };

    template<Int MOD,bool IsPrime>
    ModInt<MOD,IsPrime> operator+(ModInt<MOD,IsPrime> lhs,ModInt<MOD,IsPrime> rhs){return lhs+=rhs;};
    template<Int MOD,bool IsPrime>
    ModInt<MOD,IsPrime> operator+(ModInt<MOD,IsPrime> lhs,int rhs){return lhs+ModInt<MOD,IsPrime>(rhs);}
    template<Int MOD,bool IsPrime>
    ModInt<MOD,IsPrime> operator+(ModInt<MOD,IsPrime> lhs,ll rhs){return lhs+ModInt<MOD,IsPrime>(rhs);}
    template<Int MOD,bool IsPrime>
    ModInt<MOD,IsPrime> operator+(int lhs,ModInt<MOD,IsPrime> rhs){return ModInt<MOD,IsPrime>(lhs)+rhs;}
    template<Int MOD,bool IsPrime>
    ModInt<MOD,IsPrime> operator+(ll lhs,ModInt<MOD,IsPrime> rhs){return ModInt<MOD,IsPrime>(lhs)+rhs;}

    template<Int MOD,bool IsPrime>
    ModInt<MOD,IsPrime> operator+(ModInt<MOD,IsPrime> mn){return mn;};
    template<Int MOD,bool IsPrime>
    ModInt<MOD,IsPrime> operator-(ModInt<MOD,IsPrime> mn){return ModInt<MOD,IsPrime>(-mn.get());};

    template<Int MOD,bool IsPrime>
    ModInt<MOD,IsPrime> operator-(ModInt<MOD,IsPrime> lhs,ModInt<MOD,IsPrime> rhs){return lhs-=rhs;};
    template<Int MOD,bool IsPrime>
    ModInt<MOD,IsPrime> operator-(ModInt<MOD,IsPrime> lhs,int rhs){return lhs-ModInt<MOD,IsPrime>(rhs);};
    template<Int MOD,bool IsPrime>
    ModInt<MOD,IsPrime> operator-(ModInt<MOD,IsPrime> lhs,ll rhs){return lhs-ModInt<MOD,IsPrime>(rhs);};
    template<Int MOD,bool IsPrime>
    ModInt<MOD,IsPrime> operator-(int lhs,ModInt<MOD,IsPrime> rhs){return ModInt<MOD,IsPrime>(lhs)-rhs;};
    template<Int MOD,bool IsPrime>
    ModInt<MOD,IsPrime> operator-(ll lhs,ModInt<MOD,IsPrime> rhs){return ModInt<MOD,IsPrime>(lhs)-rhs;};

    template<Int MOD,bool IsPrime>
    ModInt<MOD,IsPrime> operator*(ModInt<MOD,IsPrime> lhs,ModInt<MOD,IsPrime> rhs){return lhs*=rhs;};
    template<Int MOD,bool IsPrime>
    ModInt<MOD,IsPrime> operator*(ModInt<MOD,IsPrime> lhs,int rhs){return lhs*ModInt<MOD,IsPrime>(rhs);}
    template<Int MOD,bool IsPrime>
    ModInt<MOD,IsPrime> operator*(ModInt<MOD,IsPrime> lhs,ll rhs){return lhs*ModInt<MOD,IsPrime>(rhs);}
    template<Int MOD,bool IsPrime>
    ModInt<MOD,IsPrime> operator*(ll lhs,ModInt<MOD,IsPrime> rhs){return ModInt<MOD,IsPrime>(lhs)*rhs;}
    template<Int MOD,bool IsPrime>
    ModInt<MOD,IsPrime> operator*(int lhs,ModInt<MOD,IsPrime> rhs){return ModInt<MOD,IsPrime>(lhs)*rhs;}

    template<Int MOD>
    ModInt<MOD,true> operator/(ModInt<MOD,true> lhs,ModInt<MOD,true> rhs);
    template<Int MOD,bool IsPrime>
    ModInt<MOD,IsPrime> powm(ModInt<MOD,IsPrime> x,Int k);
    template<Int MOD>
    ModInt<MOD,true> inv(ModInt<MOD,true> x){return powm(x,MOD-2);}

    template<Int MOD,bool IsPrime>
    std::ostream& operator<<(std::ostream& os,const ModInt<MOD,IsPrime> &mn);
    

    template<Int MOD,bool IsPrime>
    ModInt<MOD,IsPrime>& ModInt<MOD,IsPrime>::operator+=(ModInt<MOD,IsPrime> rhs){
        n+=rhs.n;
        n= n>=MOD ? n-MOD : n;
        return *this;
    }
    
    template<Int MOD,bool IsPrime>
    ModInt<MOD,IsPrime>& ModInt<MOD,IsPrime>::operator-=(ModInt rhs){
        n=n-rhs.n<0 ? n-rhs.n+MOD : n-rhs.n;
        return *this;
    }
    template<Int MOD,bool IsPrime>
    ModInt<MOD,IsPrime>& ModInt<MOD,IsPrime>::operator*=(ModInt<MOD,IsPrime> rhs){
        n=ll(n)*rhs.n%MOD;
        return *this;
    }
    
    template<Int MOD>
    ModInt<MOD,true> operator/(ModInt<MOD,true> lhs,ModInt<MOD,true> rhs){
        return lhs*inv(rhs);
    }
    template<Int MOD,bool IsPrime>
    ModInt<MOD,IsPrime> powm(ModInt<MOD,IsPrime> x,Int k){
        ModInt<MOD,IsPrime> res(1);
        while(k){
            if(k&1) res*=x;
            k>>=1;
            x*=x;
        }
        return res;
    }

    template<Int MOD,bool IsPrime>
    std::ostream& operator<<(std::ostream& os,const ModInt<MOD,IsPrime> &mn){
        os<<mn.get();
        return os;
    }

    template<Int MOD,bool IsPrime>
    std::istream& operator>>(std::istream& is,ModInt<MOD,IsPrime> &mn){
        Int tmp;
        is>>tmp;
        mn.set(tmp);
        return is;
    }
}


namespace ProconLib{

    template<typename MInt>
    class ModCombination{
        int N;
        std::vector<MInt> fact;
        std::vector<MInt> factInv;
        public:
        ModCombination(int n);
        MInt F(int n){return fact[n];}
        MInt FI(int n){return factInv[n];}
        MInt P(int n,int k){return fact[n]*factInv[n-k];}
        MInt PI(int n,int k){return factInv[n]*fact[n-k];}
        MInt C(int n,int k){return fact[n]*factInv[k]*factInv[n-k];}
        MInt CI(int n,int k){return factInv[n]*fact[k]*fact[n-k];}
    };

    template<typename MInt>
    ModCombination<MInt>::ModCombination(int n):N(n),fact(n+1),factInv(n+1){
        fact[0]=MInt(1);
        for(int i=1;i<=n;i++) fact[i]=fact[i-1]*MInt(i);
        factInv[n]=inv(fact[n]);
        for(int i=n-1;i>=0;i--){
            factInv[i]=factInv[i+1]*MInt(i+1);
        }
    }
    
}

using namespace ProconLib;

const ll MOD=998244353;
using Mint=ModInt<MOD>;

const int SIZE=3*1e6+1;
int main(){
    int n;
    cin>>n;
    int m;
    cin>>m;
    ModCombination<Mint> mc(SIZE);

    Mint res=0;
    Mint val=0;
    for(int i=m;i>=0;i-=2){
        int x=(3*m-i)/2;
        if(x==m){
            val=mc.C(n-2,n-2);
        }
        else{
            val=val+mc.C(x-m+n-2,n-2);
        }
        Mint rhs=mc.C(x+n-1,n-1)-n*val;
        Mint lhs=(i<=n ? mc.C(n,i) : Mint(0));
        res+=lhs*rhs;
    }
    res+=n*mc.C(m+n-2,n-2);
    cout<<res<<endl;
    return 0;
}

Measured memory_bytes: 23680