#include #include using i64=int64_t; using u64=uint64_t; using namespace std; namespace ttl{ template using Vec=vector; template using Vec2D=vector>; template using Vec3D=vector>>; template using Vec4D=vector>>>; template void Scan_(T& a){ cin>>a; } template void Scan_(pair& a){ Scan_(a.first),Scan_(a.second); } template void Scan_(Vec& a){ for(auto& v:a){ Scan_(v); } } template void Scan_(Vec2D& a){ for(auto& v:a){ for(auto& u:v){ Scan_(u); } } } void Scan(){} template void Scan(T& n,Args&... args){ Scan_(n),Scan(args...); } template void Print_(T a){ cout< void Print_(pair a){ Print_(a.first),cout<<" ";Print_(a.second); } template void Print(Vec a){ for(size_t i=0;i void Print(Vec2D a){ for(auto& v:a){ for(size_t i=0;i void Print(T a){ Print_(a); cout<<"\n"; } template void Print(T a,Args... args){ Print_(a),cout<<" ",Print(args...); } i64 Sum(vector a){ return accumulate(a.begin(),a.end(),i64(0)); } Vec LISSize(Vec A){ int N=A.size(); Vec dp(N+1,2e18),res(N+1); dp[0]=-1; for(int i=0;i A){ int N=A.size(); auto B=A; sort(B.begin(),B.end()); B.erase(unique(B.begin(),B.end()),B.end()); map mp; for(size_t i=0;i fwt(N); i64 ans=0; for(int i=0;i lpf; ESieve(int n_):n(n_),lpf(n_+1,-1){ for(i64 p=2;p<=n;++p){ if(lpf[p]!=-1){ continue; } for(i64 q=p;q<=n;q+=p){ if(lpf[q]==-1){ lpf[q]=p; } } } } Vec> operator()(int m){ Vec v; while(m!=1){ v.emplace_back(lpf[m]); m/=lpf[m]; } if(v.size()==0){ return {}; } Vec> res; res.emplace_back(v[0],1); for(size_t i=1;i> PrimeFact(i64 n){ Vec> res; for(i64 i=2;i*i<=n;++i){ if(n%i!=0){ continue; } i64 ex=0; while(n%i==0){ ex++,n/=i; } res.emplace_back(i,ex); } if(n!=1){ res.emplace_back(n,1); } return res; } Vec EnumDiv(i64 n){ Vec res; for(i64 i=1;i*i<=n;++i){ if(n%i!=0){ continue; } res.emplace_back(i); if(i*i!=n){ res.emplace_back(n/i); } } sort(res.begin(),res.end()); return res; } u64 Popcnt(u64 k){ return __builtin_popcountll(k); } template Vec> RunLenEnc(Vec a){ int n=a.size(); Vec> res; T now=a[0]; int l=1; for(int i=1;i StrToVec(string S){ Vec res; for(auto v:S){ res.emplace_back(v); } return res; } i64 SqrtF(i64 n){ i64 ok=0,ng=1e9+5; while(std::abs(ok-ng)>1){ i64 mid=(ok+ng)/2; (mid*mid<=n?ok:ng)=mid; } return ok; } i64 FDiv(i64 a,i64 b){ if(b<0){ a*=-1,b*=-1; } if(a<0){ return -(-a+b-1)/b; } return a/b; } i64 CDiv(i64 a,i64 b){ if(b<0){ a*=-1,b*=-1; } if(a<0){ return -(-a)/b; } return (a+b-1)/b; } template struct Comb{ vector dat,idat; Comb(int mx=3000000):dat(mx+1,1),idat(mx+1,1){ for(int i=1;i<=mx;++i){ dat[i]=dat[i-1]*i; } idat[mx]/=dat[mx]; for(int i=mx;i>0;--i){ idat[i-1]=idat[i]*i; } } T operator()(int n,int k){ if(n<0||k<0||n struct Modint{ u64 val; Modint(i64 val_=0):val((val_%i64(mod)+i64(mod))%i64(mod)){} Modint operator-(){ return (val==0)?0:mod-val; } Modint operator+(Modint rhs){ return Modint(*this)+=rhs; } Modint operator-(Modint rhs){ return Modint(*this)-=rhs; } Modint operator*(Modint rhs){ return Modint(*this)*=rhs; } Modint operator/(Modint rhs){ return Modint(*this)/=rhs; } Modint pow(i64 rhs){ Modint res=1,now=(*this); while(rhs){ res*=((rhs&1)?now:1),now*=now,rhs>>=1; } return res; } Modint &operator+=(Modint rhs){ val+=rhs.val,val-=((val>=mod)?mod:0); return (*this); } Modint &operator-=(Modint rhs){ val+=((val>(std::istream& is,Modint& x){ u64 t; is>>t,x=t; return is; } }; using namespace ttl; int main(){ constexpr u64 mod=998244353; using mint=Modint; int N; string S; Scan(N,S); int t=count(S.begin(),S.end(),'A')+count(S.begin(),S.end(),'B'); int u=count(S.begin(),S.end(),'C')+count(S.begin(),S.end(),'D'); Comb Cb; Print(Cb(t+u,t)); }