Problem:
J: GCD swap
問題
$1,2, \ldots, 9$ からなる長さ $N$ の数列 $A = (a_1, \cdots, a_N)$ が与えられます。この数列に対し、以下の操作を 0 回以上の任意の回数行うことができます。
$1 \le i \le N-1$ かつ $gcd(a_i, a_{i+1}) = 1$ である $a_i, a_{i+1}$ を選び、 順番を入れ替える。
この操作によってできる数列は何通りありますか？ただし答えは非常に大きくなる可能性があるので、 $998244353$ で割った余りを答えてください。
入力形式
入力は以下の形式で与えられる。
$N$
$a_1$ $\ldots$ $a_N$
制約
$2 \leq N \leq 100{,}000$
$1 \leq a_i \leq 9$
入力は全て整数
出力形式
答えを一行に出力し、最後に改行を入れてください。
入力例 1
3
8 3 2
出力例 1
3
$832$,$823$,$382$ ができます。
入力例 2
9
1 2 3 4 5 6 7 8 9
出力例 2
3024

Submitted solutions:

code_snippet: /*
 * @uni_kakurenbo
 * https://github.com/uni-kakurenbo/competitive-programming-workspace
 *
 * CC0 1.0  http://creativecommons.org/publicdomain/zero/1.0/deed.ja
 */
/* #language C++ 20 GCC */
// #define DEBUGGER_ENABLED

// #include "template/standard.hpp"

#include <bits/stdc++.h>

void solve();

signed main() {
    // debug(__cplusplus);
    int $ = 1;
    // std::cin >> $;
    for(int _ = 0; _ < $; ++_) {
        // debug_("Case: #" + std::to_string(_));
        solve();
    }
    return 0;
}

#include <atcoder/lazysegtree.hpp>
/* [begin]: template/warnings.hpp */
#pragma GCC diagnostic warning "-Wshadow=local"
/* [end]: template/warnings.hpp*/

#include <iostream>
using namespace std;

#include <atcoder/modint>
using mint = atcoder::modint998244353;

const int MAX = 510000;
mint fac[MAX], finv[MAX], inv[MAX];

void COMinit() {
    const int MOD = mint::mod();
    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;
        inv[i] = MOD - inv[MOD%i] * (MOD / i);
        finv[i] = finv[i - 1] * inv[i];
    }
}

mint 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];
}


void solve() {
    COMinit();

    int n; std::cin >> n;
    std::vector<int> a(n);
    for(auto& x : a) std::cin >> x;


    std::array<std::vector<long>, 10> ids;

    int cnt2 = 0, cnt3 = 0;
    int cnt1 = 0, cnt5 = 0, cnt7 = 0;

    mint ans = 1;

    for(int i : std::views::iota(0, n)) {
        if(a[i] % 2 == 0) ++cnt2;
        if(a[i] % 3 == 0) ++cnt3;
        if(a[i] == 6) {
            --cnt2, --cnt3;
            // std::cerr << cnt2 << ", " << cnt3 << "\n";
            ans *= COM(cnt2 + cnt3, cnt3);
            cnt2 = 0;
            cnt3 = 0;
        }
        if(a[i] == 1) ++cnt1;
        if(a[i] == 5) ++cnt5;
        if(a[i] == 7) ++cnt7;
    }

    // std::cerr << cnt2 << ", " << cnt3 << "\n";
    ans *= COM(cnt2+cnt3, cnt3);

    // std::cerr << cnt1 << ", " << cnt5 << ", " << cnt7 << "\n";
    int s = cnt1 + cnt5 + cnt7;

    auto x = (fac[n] * finv[n - s]) * finv[cnt1]* finv[cnt5]* finv[cnt7];
    // std::cerr << x.val() << "\n";
    ans *= x;

    std::cout << ans.val() << "\n";
}
accuracy: 1
time_ms: 10
memory_kb: 9672
final_rank: 6

code_snippet: #include<atcoder/all>
using namespace atcoder;

#include <bits/stdc++.h>
template<class T> inline bool chmin(T&a, T b){if(a > b){a = b; return true;}else{return false;}}
template<class T> inline bool chmax(T&a, T b){if(a < b){a = b; return true;}else{return false;}}
#define ll long long
#define double long double
#define rep(i,n) for(int i=0;i<(n);i++)
#define REP(i,n) for(int i=1;i<=(n);i++)
#define mod (ll)(1e9+7)
#define inf (ll)(3e18+7)
#define eps (double)(1e-9)
#define pi (double) acos(-1)
#define all(x) x.begin(),x.end()
#define rall(x) x.rbegin(),x.rend()
using namespace std;

using mint = modint998244353;

const int MAX = 1000005;
mint 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;
        inv[i] = (mint)1/i;
        finv[i] = finv[i-1] * inv[i];
    }
}
mint 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];
}
mint NHK(int n,int k){
	return COM(n+k-1,k);
}

int main() {
    COMinit();
    int n;
    cin >> n;

    vector<int> a(n);
    rep(i, n)cin >> a[i];
    rep(i, n)if(a[i] == 4)a[i] = 2;
    rep(i, n)if(a[i] == 8)a[i] = 2;
    rep(i, n)if(a[i] == 9)a[i] = 3;
    a.push_back(6);

    mint ans = 1;
    ll CNT1 = 0;
    ll CNT5 = 0;
    ll CNT7 = 0;
    ll cnt2 = 0, cnt3 = 0;
    rep(i, n+1) {
        if(a[i] == 6) {
            ans *= COM(cnt2 + cnt3, cnt2);
            cnt2 = 0;
            cnt3 = 0;
        }
        if(a[i] == 2)cnt2++;
        if(a[i] == 3)cnt3++;
    }

    rep(i, n)CNT1 += (a[i] == 1);
    rep(i, n)CNT5 += (a[i] == 5);
    rep(i, n)CNT7 += (a[i] == 7);

    ans *= COM(n, CNT1+CNT5+CNT7);
    ans *= COM(CNT1+CNT5+CNT7, CNT1);
    ans *= COM(CNT5+CNT7, CNT5);

    cout << ans.val() << endl;

}
accuracy: 1
time_ms: 80
memory_kb: 15944
final_rank: 13

code_snippet: #include<atcoder/all>
using namespace atcoder;

#include <bits/stdc++.h>
template<class T> inline bool chmin(T&a, T b){if(a > b){a = b; return true;}else{return false;}}
template<class T> inline bool chmax(T&a, T b){if(a < b){a = b; return true;}else{return false;}}
#define ll long long
#define double long double
#define rep(i,n) for(int i=0;i<(n);i++)
#define REP(i,n) for(int i=1;i<=(n);i++)
#define mod (ll)(1e9+7)
#define inf (ll)(3e18+7)
#define eps (double)(1e-9)
#define pi (double) acos(-1)
#define all(x) x.begin(),x.end()
#define rall(x) x.rbegin(),x.rend()
using namespace std;

using mint = modint998244353;

const int MAX = 1000005;
mint 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;
        inv[i] = (mint)1/i;
        finv[i] = finv[i-1] * inv[i];
    }
}
mint 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];
}
mint NHK(int n,int k){
	return COM(n+k-1,k);
}

int main() {
    COMinit();
    int n;
    cin >> n;

    vector<int> a(n);
    rep(i, n)cin >> a[i];
    rep(i, n)if(a[i] == 4)a[i] = 2;
    rep(i, n)if(a[i] == 8)a[i] = 2;
    rep(i, n)if(a[i] == 9)a[i] = 3;
    a.push_back(6);

    mint ans = 1;
    ll CNT = 0;
    ll cnt2 = 0, cnt3 = 0;
    rep(i, n+1) {
        if(a[i] == 6) {
            ans *= COM(cnt2 + cnt3, cnt2);
            cnt2 = 0;
            cnt3 = 0;
        }
        if(a[i] == 2)cnt2++;
        if(a[i] == 3)cnt3++;
    }

    rep(i, n)CNT += (a[i] == 1);
    rep(i, n)CNT += (a[i] == 5);
    rep(i, n)CNT += (a[i] == 7);

    ans *= COM(n, CNT);
    for(int i = CNT; i >= 1; i--)ans *= i;

    cout << ans.val() << endl;

}
accuracy: 0.04225352112676056
time_ms: 70
memory_kb: 15308
final_rank: 16

code_snippet: #include<atcoder/all>
using namespace atcoder;

#include <bits/stdc++.h>
template<class T> inline bool chmin(T&a, T b){if(a > b){a = b; return true;}else{return false;}}
template<class T> inline bool chmax(T&a, T b){if(a < b){a = b; return true;}else{return false;}}
#define ll long long
#define double long double
#define rep(i,n) for(int i=0;i<(n);i++)
#define REP(i,n) for(int i=1;i<=(n);i++)
#define mod (ll)(1e9+7)
#define inf (ll)(3e18+7)
#define eps (double)(1e-9)
#define pi (double) acos(-1)
#define all(x) x.begin(),x.end()
#define rall(x) x.rbegin(),x.rend()
using namespace std;

using mint = modint998244353;

const int MAX = 1000005;
mint 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;
        inv[i] = (mint)1/i;
        finv[i] = finv[i-1] * inv[i];
    }
}
mint 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];
}
mint NHK(int n,int k){
	return COM(n+k-1,k);
}

int main() {
    COMinit();
    int n;
    cin >> n;

    vector<int> a(n);
    rep(i, n)cin >> a[i];
    rep(i, n)if(a[i] == 4)a[i] = 2;
    rep(i, n)if(a[i] == 8)a[i] = 2;
    rep(i, n)if(a[i] == 9)a[i] = 3;
    a.push_back(6);

    mint ans = 1;
    int CNT = 0;
    int cnt2 = 0, cnt3 = 0;
    rep(i, n+1) {
        if(a[i] == 6) {
            ans *= COM(cnt2 + cnt3, cnt2);
            CNT += cnt2 + cnt3;
            cnt2 = 0;
            cnt3 = 0;
        }
        if(a[i] == 2)cnt2++;
        if(a[i] == 3)cnt3++;
    }

    rep(i, n)CNT += (a[i] == 6);

    ans *= COM(n, CNT);
    for(int i = n-CNT; i >= 1; i--)ans *= i;

    cout << ans.val() << endl;

}
accuracy: 0.04225352112676056
time_ms: 70
memory_kb: 15308
final_rank: 16

code_snippet: // #pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#include <atcoder/all>
using namespace atcoder;
using namespace std;

using ll = long long;
using ull = unsigned long long;
using vecint = std::vector<int>;
using vecll = std::vector<long long>;
using vecstr = std::vector<string>;
using vecbool = std::vector<bool>;
using vecdou = std::vector<double>;
using vecpl = std::vector<pair<ll,ll>>;
using vec2d = std::vector<vecll>;
using vec2di = std::vector<vecint>;
using vec2dd = std::vector<vecdou>;
using vec2db = std::vector<vecbool>;
using pl = pair<long long,long long>;
using mint998 = modint998244353;
using mint107 = modint1000000007;
using mint = modint;
using vecmint = std::vector<mint>;
using vecmint998 = std::vector<mint998>;
using vecmint107 = std::vector<mint107>;
using vec2dmint = std::vector<vecmint>; 
using vec2dmint998 = std::vector<vecmint998>;
using vec2dmint107 = std::vector<vecmint107>;
#define rep(i,n) for (ll i = 0; i < (ll)(n); i++)
#define rep1(i,n) for (ll i = 1; i <= (ll)(n); i++)
#define REP(i,l,r) for (ll i = (ll)(l); i < (ll)(r); i++)
#define rrep(i,n) for (ll i = (ll)(n)-1; i >= 0; i--)
#define rrep1(i,n) for (ll i = (ll)(n); i > 0; i--)
#define RREP(i,l,r) for (ll i = (ll)(r)-1; i >= (ll)(l); i--)
#define all(a) (a).begin(), (a).end()
#define INF ((1LL<<62)-(1LL<<31))
#define inr(a,x,b) ((a) <= (x) && (x) < (b))
template <typename T>
bool chmax(T &a, const T &b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}
template <typename T>
bool chmin(T &a, const T &b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}

void ynout(bool x,string Tru="Yes",string Wro="No"){
    if(x){
        cout << Tru << '\n';
    }else{
        cout << Wro << '\n';
    }
}
ll power(ll a,ll b,ll mod=INF){
    long long x=1,y=a%mod;
    while(b>0){
        if(b&1ll){
            x=(x*y)%mod;
        }
        y=(y*y)%mod;
        b>>=1;
    }
  return x%mod;
}
ll Pdist2(pair<ll,ll> a,pair<ll,ll> b){
    return (a.first-b.first)*(a.first-b.first)+(a.second-b.second)*(a.second-b.second);
}
double Pdist(pair<ll,ll> a,pair<ll,ll> b){
    return sqrt(Pdist2(a,b));
}
ll PdistM(pair<ll,ll> a,pair<ll,ll> b){
    return abs(a.first-b.first)+abs(a.second-b.second);
}
ll gcd(ll a,ll b){
    if(b==0){
        return a;
    }else{
        return gcd(b,a%b);
    }
}
ll lcm(ll a,ll b){
    return a/gcd(a,b)*b;
}

void solve();

int main() {
    std::cin.tie(nullptr);
    std::ios::sync_with_stdio(false);
    ll t=1;
    //std::cin >> t;
    rep(i,t)solve();
}

vecll dx = {1,0,-1,0};
vecll dy = {0,1,0,-1};

void solve(){
    ll n;
    cin>>n;
    vecll a(n);
    rep(i,n)cin>>a[i];
    vecll c(10,0);
    rep(i,n)c[a[i]]++;
    mint998 ans=1;
    ll cs=c[1]+c[5]+c[7];
    rep1(i,cs)ans*=i;
    rep1(i,c[1])ans/=i;
    rep1(i,c[5])ans/=i;
    rep1(i,c[7])ans/=i;
    ll c2=0;
    ll c3=0;
    ll c23=0;
    rep(i,n){
        if(a[i]%2==0||a[i]%3==0)c23++;
        if(a[i]==6){
            if(c2==0&&c3==0)continue;
            rep1(j,c2+c3)ans*=j;
            rep1(j,c2)ans/=j;
            rep1(j,c3)ans/=j;
            c2=0;
            c3=0;
        }else if(a[i]%2==0)c2++;
        else if(a[i]%3==0)c3++;
    }
    if(c2==0&&c3==0){

    }
    else{
        rep1(j,c2+c3)ans*=j;
        rep1(j,c2)ans/=j;
        rep1(j,c3)ans/=j;
        c2=0;
        c3=0;
    }
    rep1(i,n)ans*=i;
    rep1(i,c23)ans/=i;
    rep1(i,n-c23)ans/=i;
    cout<<ans.val()<<'\n';
}
accuracy: 1
time_ms: 10
memory_kb: 4096
final_rank: 1

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, a, b) for (int i = a; i < (b); i++)
#define all(a) (a).begin(), (a).end()

const ll mod = 998244353;
struct mm {
   ll x;
   mm(ll x_ = 0) : x(x_ % mod) {
      if(x < 0) x += mod;
   }
   friend mm operator+(mm a, mm b) { return a.x + b.x; }
   friend mm operator-(mm a, mm b) { return a.x - b.x; }
   friend mm operator*(mm a, mm b) { return a.x * b.x; }
   friend mm operator/(mm a, mm b) { return a * b.inv(); }
   // 4 行コピペ  Alt + Shift + クリックで複数カーソル
   friend mm& operator+=(mm& a, mm b) { return a = a.x + b.x; }
   friend mm& operator-=(mm& a, mm b) { return a = a.x - b.x; }
   friend mm& operator*=(mm& a, mm b) { return a = a.x * b.x; }
   friend mm& operator/=(mm& a, mm b) { return a = a * b.inv(); }
   mm inv() const { return pow(mod - 2); }
   mm pow(ll b) const {
      mm a = *this, c = 1;
      while(b) {
         if(b & 1) c *= a;
         a *= a;
         b >>= 1;
      }
      return c;
   }
};

int main(){
    int N = 5'000'000;
    vector<mm> fact(N, 1);
    rep(i, 2, N){
        fact[i] = fact[i-1] * i;
    }

    int n;
    cin >> n;
    vector<int> a(n);
    vector<array<int,2>> tt = {{0,0}};
    int c1=0,c5=0,c7=0,el=0;
    rep(i, 0 ,n){
        cin >> a[i];
        if(a[i] == 1) c1++;
        else if (a[i] == 5) c5++;
        else if (a[i] == 7) c7++;
        else{
            if(a[i] == 6) tt.push_back({0, 0});
            else if(a[i] % 2 == 0) tt.back()[0]++;
            else tt.back()[1]++;
            el++;
        }
    }

    mm ans = 1;
    ans *= fact[n];
    ans /= fact[c1];
    ans /= fact[c5];
    ans /= fact[c7];
    ans /= fact[el];
    for(auto [o,t] : tt){
        ans *= fact[o+t] / fact[o] / fact[t];
    }

    cout << ans.x << endl;
}
accuracy: 1
time_ms: 30
memory_kb: 43232
final_rank: 12

code_snippet: #include <bits/stdc++.h>

template <std::uint32_t MOD>
class ModInt {
	std::uint32_t value;
	friend std::ostream &operator<<(std::ostream &os, const ModInt &x){ return os << x.value; }
	friend std::istream &operator>>(std::istream &is, ModInt &x){ is >> x.value; x.value %= MOD; return is; }
public:
	constexpr ModInt(std::uint32_t x = 0): value(x % MOD) {}
	constexpr ModInt operator-() const { return value == 0 ? 0 : MOD - value; }
	constexpr ModInt &operator+=(const ModInt &other){ if(value < MOD - other.value) value += other.value; else value -= MOD - other.value; return *this; }
	constexpr ModInt &operator-=(const ModInt &other){ if(value >= other.value) value -= other.value; else value += MOD - other.value; return *this; }
	constexpr ModInt &operator*=(const ModInt &other){ value = static_cast<std::uint64_t>(value) * other.value % MOD; return *this; }
	constexpr ModInt &operator/=(const ModInt &other){ return *this *= other.inv(); }
	friend constexpr ModInt operator+(ModInt left, const ModInt &right){ return left += right; }
	friend constexpr ModInt operator-(ModInt left, const ModInt &right){ return left -= right; }
	friend constexpr ModInt operator*(ModInt left, const ModInt &right){ return left *= right; }
	friend constexpr ModInt operator/(ModInt left, const ModInt &right){ return left /= right; }
	constexpr ModInt inv() const { unsigned a = MOD, s = 0; unsigned b = value, t = 1; bool sign = true; while(b){ s += t * (a / b); a %= b; sign = !sign; std::swap(a, b); std::swap(s, t); } if(sign) s = MOD - s; return s; }
	constexpr ModInt pow(unsigned n) const { ModInt tmp = *this, ret = 1; while(n){ if(n % 2) ret *= tmp; tmp *= tmp; n /= 2; } return ret; }
};

template <std::uint32_t MOD>
struct Factorials {
	std::vector<ModInt<MOD>> fac, finv, inv;
	Factorials(std::size_t n) : fac(n, 1), finv(n, 1), inv(n, 1) {
		for(int i = 2; i < n; i++){
			fac[i] = fac[i - 1] * i;
			inv[i] = -inv[MOD % i] * (MOD / i);
			finv[i] = finv[i - 1] * inv[i];
		}
	}
	ModInt<MOD> factorial(std::size_t n) const { return fac[n]; }
	ModInt<MOD> permutation(std::size_t n, std::size_t k) const { return fac[n] * finv[n - k]; }
	ModInt<MOD> combination(std::size_t n, std::size_t k) const { return fac[n] * finv[k] * finv[n - k]; }
};

int main(){
	int n;
	std::cin >> n;
	int count1 = 0, count2 = 0, count3 = 0;
	const Factorials<998244353> f(n + 1);
	ModInt<998244353> ans = 1;
	std::vector<int> count(10);
	for(int i = 0; i <= n; i++){
		int a;
		if(i < n){
			std::cin >> a;
			count[a]++;
		}
		if(i == n || a == 6){
			ans *= f.fac[count[2] + count[3] + count[4] + count[8] + count[9]]
				* f.finv[count[2] + count[4] + count[8]]
				* f.finv[count[3] + count[9]];
			count[2]
			= count[3]
			= count[4]
			= count[8]
			= count[9]
			= 0;
		}
	}
	ans *= f.fac[n]
		* f.finv[count[1]]
		* f.finv[count[5]]
		* f.finv[count[7]]
		* f.finv[n - count[1] - count[5] - count[7]];
	std::cout << ans << std::endl;
}
accuracy: 1
time_ms: 10
memory_kb: 4312
final_rank: 2

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
#define chmin(x,y) x = min(x,y)
#define chmax(x,y) x = max(x,y)
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
//#define MOD 1000000007
#define EPS 0.000000001



#define MOD 998244353
#define SIZE 1000005

ll N;
ll A[SIZE];
ll fact[SIZE],inv_fact[SIZE];

ll mod_pow(ll x,ll count, ll mod){

	if(count == 0)return 1;
	ll ret = mod_pow(((x%mod)*(x%mod))%mod,count/2,mod);
	if(count%2 == 1){

		ret = ((ret%mod)*(x%mod))%mod;
	}
	return ret;
}


ll euler_phi(ll num){

	 ll ret = num;

	 for(ll i = 2; i*i <= num;  i++){
			if(num%i == 0) {
				  ret  = ret/i*(i-1);
				  while(num%i == 0)num /= i;
			}
	  }
	  if(num != 1) ret = ret/num*(num-1);
	  return ret;
}


ll extgcd(ll a,ll b,ll &x,ll &y){
	ll d = a;
	if(b != 0){
		d = extgcd(b,a%b,y,x);
		y -= (a/b)*x;
	}else{
		x = 1;
		y = 0;
	}
	return d;
}

ll mod_inverse(ll a,ll m){
    ll x,y;
    extgcd(a,m,x,y);
    return (m+x%m)%m;
}

ll nCk(ll n,ll k){

	if(k > n)return 0;

	ll ret = fact[n]*inv_fact[k];
	ret %= MOD;
	ret *= inv_fact[n-k];

	return ret%MOD;
}

ll nPk(ll n,ll k){

	if(k > n)return 0;

	ll ret = fact[n]*inv_fact[n-k];

	return ret%MOD;
}



int main(){

	fact[0] = 1;
	for(ll i = 1; i < SIZE; i++){
		fact[i] = i*fact[i-1];
		fact[i] %= MOD;
	}
	inv_fact[SIZE-1] = mod_inverse(fact[SIZE-1],MOD);
	for(ll i = SIZE-1; i >= 1; i--){

		inv_fact[i-1] = inv_fact[i]*i;
		inv_fact[i-1] %= MOD;
	}

	scanf("%lld",&N);

	ll minus = 0;
	ll num1 = 0,num5 = 0,num7 = 0;
	vector<ll> vec;
	vec.push_back(-1); //ダミー

	for(ll i = 0; i < N; i++){

		scanf("%lld",&A[i]);
		if(A[i] == 1 || A[i] == 5 || A[i] == 7){

			minus++;
			if(A[i] == 1){

				num1++;
			}else if(A[i] == 5){

				num5++;
			}else{

				num7++;
			}

		}else if(A[i] == 6){

			vec.push_back(i);
		}
	}
	vec.push_back(N); //ダミー

	ll ans = 1;
	for(ll i = 0; i < vec.size()-1; i++){
		ll num2 = 0,num3 = 0;
		for(ll k = vec[i]+1; k < vec[i+1]; k++){
			if(A[k]%2 == 0){

				num2++;
			}
			if(A[k]%3 == 0){

				num3++;
			}
		}

		ans *= nCk(num2+num3,num2);
		ans %= MOD;
	}

	ans *= nCk(N,num1);
	ans %= MOD;
	ans *= nCk(N-num1,num5);
	ans %= MOD;
	ans *= nCk(N-(num1+num5),num7);
	ans %= MOD;

	printf("%lld\n",ans);

	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 19808
final_rank: 9

code_snippet: #include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <array>
#include <algorithm>
#include <numeric>
#include <unordered_map>
#include <unordered_set>
#include <map>
#include <set>
#include <cassert>
#include <iterator>
#include <random>
#include <stack>
#include <climits>
#include <chrono>
#include <iomanip>

constexpr int MOD = 998244353;
long long int pow_mod(long long int base, int exp) {
	long long int result{ 1 };
	base %= MOD;
	while (exp > 0) {
		if (exp & 1) {
			result = result * base % MOD;
		}
		base = base * base % MOD;
		exp >>= 1;
	}
	return result;
}
int main() {
	int n; std::cin >> n;
	std::vector<int> nums(n);
	for (auto& a : nums) {
		std::cin >> a;
	}
	std::vector<long long int> factorial(n + 1, 1), inverse(n + 1, 1);
	for (auto i = 2; i <= n; ++i) {
		factorial[i] = i * factorial[i - 1] % MOD;
	}
	inverse[n] = pow_mod(factorial[n], MOD - 2);
	for (auto i = n; i >= 2; --i) {
		inverse[i - 1] = i * inverse[i] % MOD;
	}
	const auto combination = [&factorial, &inverse](const int n, const int r) {
		return factorial[n] * inverse[r] % MOD * inverse[n - r] % MOD;
	};
	int count1{ 0 }, count2{ 0 }, count3{ 0 }, count5{ 0 }, count7{ 0 };
	long long int result{ 1 };
	for (const auto a : nums) {
		if (a == 1) {
			++count1;
		}
		else if (a == 5) {
			++count5;
		}
		else if (a == 7) {
			++count7;
		}
		else if (a == 2 || a == 4 || a == 8) {
			++count2;
		}
		else if (a == 3 || a == 9) {
			++count3;
		}
		else {
			result = result * combination(count2 + count3, count2) % MOD;
			count2 = 0;
			count3 = 0;
		}
	}
	result = result * combination(count2 + count3, count2) % MOD;
	result = result * combination(n, count1 + count5 + count7) % MOD;
	result = result * combination(count1 + count5 + count7, count7) % MOD;
	result = result * combination(count1 + count5, count5) % MOD;
	std::cout << result << '\n';
}
accuracy: 1
time_ms: 10
memory_kb: 4952
final_rank: 5

code_snippet: #pragma GCC optimize("Ofast")
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <cstdio>
#include <ctime>
#include <assert.h>
#include <chrono>
#include <random>
#include <numeric>
#include <set>
#include <deque>
#include <stack>
#include <sstream>
#include <utility>
#include <cstring>
#include <unordered_map>
#include <unordered_set>
#include <tuple>
#include <array>
#include <bitset>
using namespace std;
typedef long long int ll;
typedef unsigned long long ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) {
    return (ull)rng() % B;
}
inline ll time() {
    return static_cast<long double>(chrono::duration_cast<chrono::nanoseconds>(chrono::steady_clock::now().time_since_epoch()).count()) * 1e-9;
}

constexpr ll mod = 998244353;

ll mod_pow(ll a,ll b){
    a%=mod;
    if(b==0)return 1;
    if(b==1)return a;
    ll res=mod_pow(a,b/2)%mod;
    res*=res; res%=mod;
    if(b%2)res*=a;
    return res%mod;
}

struct perm{
private:
    int sz;
    vector<ll> p,invp;
public:
    perm(int n){
        sz=n+1;
        p.resize(sz),invp.resize(sz);
        p[0]=1;
        for(int i=1;i<=sz-1;i++){
            p[i]=p[i-1]*i%mod;
        }
        invp[sz-1]=mod_pow(p[sz-1],mod-2);
        for(int i=sz-2;i>=0;i--){
            invp[i]=invp[i+1]*(i+1)%mod;
        }
    }
    ll comb(ll x,ll y){
        if(x<y||y<0)return 0;
        return (p[x]*invp[x-y]%mod)*invp[y]%mod;
    }
};
perm p(1<<20);

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n; cin >> n;
    vector<int> a;
    vector<int> cnt(10);
    for(int i=0;i<n;i++){
        int x; cin >> x;
        if(x == 1 or x == 5 or x == 7){
            cnt[x]++;
        }
        else{
            a.push_back(x);
        }
    }
    n = a.size();
    ll res = 1;
    for(int i=0;i<n;i++){
        if(a[i] == 6)continue;
        int tw = 0, th = 0;
        while(i<n and a[i] != 6){
            if(a[i]%2 == 0)tw++;
            else th++;
            i++;
        }
        res *= p.comb(tw+th,th);
        res %= mod;
    }
    vector<int> v={1,5,7};
    for(auto i:v){
        res *= p.comb(n+cnt[i], cnt[i]);
        res %= mod;
        n += cnt[i];
    }
    cout << res << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 20188
final_rank: 10

code_snippet: /**
 *   @FileName	a.cpp
 *   @Author	kanpurin
 *   @Created	2022.03.19 19:07:24
**/

#include "bits/stdc++.h" 
using namespace std; 
typedef long long ll;


template< int MOD >
struct mint {
public:
    unsigned int x;
    mint() : x(0) {}
    mint(long long v) {
        long long w = (long long)(v % (long long)(MOD));
        if (w < 0) w += MOD;
        x = (unsigned int)(w);
    }
    mint(std::string &s) {
        unsigned int z = 0;
        for (int i = 0; i < s.size(); i++) {
            z *= 10;
            z += s[i] - '0';
            z %= MOD;
        }
        x = z;
    }
    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }
    mint& operator+=(const mint &a) {
        if ((x += a.x) >= MOD) x -= MOD;
        return *this;
    }
    mint& operator-=(const mint &a) {
        if ((x -= a.x) >= MOD) x += MOD;
        return *this;
    }
    mint& operator*=(const mint &a) {
        unsigned long long z = x;
        z *= a.x;
        x = (unsigned int)(z % MOD);
        return *this;
    }
    mint& operator/=(const mint &a) {return *this = *this * a.inv(); }
    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs.x == rhs.x;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs.x != rhs.x;
    }
    friend std::ostream& operator<<(std::ostream &os, const mint &n) {
        return os << n.x;
    }
    friend std::istream &operator>>(std::istream &is, mint &n) {
        unsigned int x;
        is >> x;
        n = mint(x);
        return is;
    }
    mint inv() const {
        assert(x);
        return pow(MOD-2);
    }
    mint pow(long long n) const {        
        assert(0 <= n);
        mint p = *this, r = 1;
        while (n) {
            if (n & 1) r *= p;
            p *= p;
            n >>= 1;
        }
        return r;
    }
    
    mint sqrt() const {
        if (this->x < 2) return *this;
        if (this->pow((MOD-1)>>1).x != 1) return mint(0);
        mint b = 1, one = 1;
        while (b.pow((MOD-1) >> 1) == 1) b += one;
        long long m = MOD-1, e = 0;
        while (m % 2 == 0) m >>= 1, e += 1;
        mint x = this->pow((m - 1) >> 1);
        mint y = (*this) * x * x;
        x *= (*this);
        mint z = b.pow(m);
        while (y.x != 1) {
            int j = 0;
            mint t = y;
            while (t != one) j += 1, t *= t;
            z = z.pow(1LL << (e-j-1));
            x *= z; z *= z; y *= z; e = j;
        }
        return x;
    }
};

constexpr int MOD = 998244353;

template<typename T>
struct Combination {
private:
    int N;

public:
    vector< T > FACT, IFACT;
    Combination(int n) : N(n) {
        FACT.resize(n + 1);
        IFACT.resize(n + 1);
        FACT[0] = 1;
        for (int i = 1; i <= n; i++) {
            FACT[i] = FACT[i - 1] * i;
        }
        IFACT[n] = T(1) / FACT[n];
        for (int i = n-1; i >= 0; i--) {
            IFACT[i] = IFACT[i+1] * (i+1);
        }
    }

    T comb(int n, int r) {
        if (n < 0 || r < 0 || r > n) return 0;
        if (r > n / 2) r = n - r;
        return FACT[n] * IFACT[n - r] * IFACT[r];
    }
};

int main() {
    int n;cin >> n;
    Combination<mint<MOD>> cb(n);
    vector<int> a(n);
    int p1 = 0, p2 = 0, c1 = 0, c23 = 0, c5 = 0, c7 = 0;
    mint<MOD> ans = 1;
    for (int i = 0; i < n; i++) {
        cin >> a[i];
        if (a[i] == 2 || a[i] == 4 || a[i] == 8) {
            p1++;
            c23++;
        }
        else if (a[i] == 3 || a[i] == 9) {
            p2++;
            c23++;
        }
        else if (a[i] == 6) {
            ans *= cb.comb(p1+p2,p1);
            p1 = 0;
            p2 = 0;
            c23++;
        }
        else if (a[i] == 1) {
            c1++;
        }
        else if (a[i] == 5) {
            c5++;
        }
        else if (a[i] == 7) {
            c7++;
        }
        if (i==n-1) {
            ans *= cb.comb(p1+p2,p1);
            ans *= cb.FACT[n]*cb.IFACT[c1]*cb.IFACT[c23]*cb.IFACT[c5]*cb.IFACT[c7];
        }
    }
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 4316
final_rank: 3

code_snippet: /*
考えたこと：
(1) 2の倍数同士はswapできない
(2) 3の倍数同士はswapできない
それ以外はswapできる。
(1) だけなら、偶数を赤、奇数を白としたときに、赤の相対順序が固定化されて、それ以外は自由。
(2) を入れるなら、2の倍数は赤、3の倍数は青、ただし6は紫で、それ以外は白とすると
・白はあとから自由に挿入できるので、以降 0 個として本質を失わない。
・(赤+青) 紫 (赤+青) の構造を考えると、左側と右側で独立に数えられる。
・赤+青の構造では、赤の相対順と青の相対順が固定化され、それ以外は自由なので、重複数え上げ。
計算量は O(N) になる。

考察上の見落とし：
・6が複数含まれるケース。それぞれ独立に計算が必要。
・1, 5, 7 でも同じ値同士は区別できないので、適当に割る必要がある。

実装上の注意：AtCoder Libraryはそのままでは利用できない
*/

#include <iostream>
#include <vector>
#define rep(i, n) for(i = 0; i < n; i++)
#define int long long
using namespace std;

int mod = 998244353;
int n;
int a[100000];
int fact[100001];
int finv[100001];

int powmod(int a, int n, int mod) {
	if (n == 0) return 1;
	if (n % 2 == 0) return powmod((a * a) % mod, n / 2, mod);
	return a * powmod(a, n - 1, mod) % mod;
}

signed main() {
	int i, j;
	
	fact[0] = 1;
	finv[0] = 1;
	rep(i, 100000) {
		fact[i + 1] = (i + 1) * fact[i] % mod;
		finv[i + 1] = powmod(fact[i + 1], mod - 2, mod);
	}
	
	cin >> n;
	rep(i, n) cin >> a[i];
	
	vector<int> pos6;
	pos6.push_back(-1);
	rep(i, n) if (a[i] == 6) { pos6.push_back(i); }
	pos6.push_back(n);
	
	int ans = 1;
	
	rep(i, (int)pos6.size() - 1) {
		int red = 0, blue = 0;
		for (j = pos6[i] + 1; j < pos6[i + 1]; j++) {
			if (a[j] % 2 == 0) { red++; }
			if (a[j] % 3 == 0) { blue++; }
		}
		ans *= fact[red + blue]; ans %= mod;
		ans *= finv[red]; ans %= mod;
		ans *= finv[blue]; ans %= mod;
	}
	
	int white = 0;
	rep(i, n) {
		if (a[i] % 2 != 0 && a[i] % 3 != 0) { white++; }
	}
	for (i = n - white + 1; i <= n; i++) { ans *= i; ans %= mod; }
	
	int cnt[10] = {0};
	rep(i, n) {
		cnt[a[i]]++;
	}
	ans *= finv[cnt[1]]; ans %= mod;
	ans *= finv[cnt[5]]; ans %= mod;
	ans *= finv[cnt[7]]; ans %= mod;
	
	cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 5628
final_rank: 11

code_snippet: /*
考えたこと：
(1) 2の倍数同士はswapできない
(2) 3の倍数同士はswapできない
それ以外はswapできる。
(1) だけなら、偶数を赤、奇数を白としたときに、赤の相対順序が固定化されて、それ以外は自由。
(2) を入れるなら、2の倍数は赤、3の倍数は青、ただし6は紫で、それ以外は白とすると
・白はあとから自由に挿入できるので、以降 0 個として本質を失わない。
・(赤+青) 紫 (赤+青) の構造を考えると、左側と右側で独立に数えられる。
・赤+青の構造では、赤の相対順と青の相対順が固定化され、それ以外は自由なので、重複数え上げ。
計算量は O(N) になる。

考察上の見落とし：6が複数含まれるケース。それぞれ独立に計算が必要。
実装上の注意：AtCoder Libraryはそのままでは利用できない
*/

#include <iostream>
#include <vector>
#define rep(i, n) for(i = 0; i < n; i++)
#define int long long
using namespace std;

int mod = 998244353;
int n;
int a[100000];
int fact[100001];
int finv[100001];

int powmod(int a, int n, int mod) {
	if (n == 0) return 1;
	if (n % 2 == 0) return powmod((a * a) % mod, n / 2, mod);
	return a * powmod(a, n - 1, mod) % mod;
}

signed main() {
	int i, j;
	
	fact[0] = 1;
	finv[0] = 1;
	rep(i, 100000) {
		fact[i + 1] = (i + 1) * fact[i] % mod;
		finv[i + 1] = powmod(fact[i + 1], mod - 2, mod);
	}
	
	cin >> n;
	rep(i, n) cin >> a[i];
	
	vector<int> pos6;
	pos6.push_back(-1);
	rep(i, n) if (a[i] == 6) { pos6.push_back(i); }
	pos6.push_back(n);
	
	int ans = 1;
	
	rep(i, (int)pos6.size() - 1) {
		int red = 0, blue = 0;
		for (j = pos6[i] + 1; j < pos6[i + 1]; j++) {
			if (a[j] % 2 == 0) { red++; }
			if (a[j] % 3 == 0) { blue++; }
		}
		ans *= fact[red + blue]; ans %= mod;
		ans *= finv[red]; ans %= mod;
		ans *= finv[blue]; ans %= mod;
	}
	
	int white = 0;
	rep(i, n) {
		if (a[i] % 2 != 0 && a[i] % 3 != 0) { white++; }
	}
	for (i = n - white + 1; i <= n; i++) { ans *= i; ans %= mod; }
	
	cout << ans << endl;
	return 0;
}
accuracy: 0.04225352112676056
time_ms: 60
memory_kb: 4672
final_rank: 14

code_snippet: /*
考えたこと：
(1) 2の倍数同士はswapできない
(2) 3の倍数同士はswapできない
それ以外はswapできる。
(1) だけなら、偶数を赤、奇数を白としたときに、赤の相対順序が固定化されて、それ以外は自由。
(2) を入れるなら、2の倍数は赤、3の倍数は青、ただし6は紫で、それ以外は白とすると
・白はあとから自由に挿入できるので、以降 0 個として本質を失わない。
・(赤+青) 紫 (赤+青) の構造を考えると、左側と右側で独立に数えられる。
・赤+青の構造では、赤の相対順と青の相対順が固定化され、それ以外は自由なので、重複数え上げ。
計算量は O(N) になる。

考察上の見落とし：6が複数含まれるケース。それぞれ独立に計算が必要。
実装上の注意：AtCoder Libraryはそのままでは利用できない
*/

#include <iostream>
#include <vector>
#define rep(i, n) for(i = 0; i < n; i++)
#define int long long
using namespace std;

int mod = 998244353;
int n;
int a[100000];
int fact[100001];
int finv[100001];

int powmod(int a, int n, int mod) {
	if (n == 0) return 1;
	if (n % 2 == 0) return powmod((a * a) % mod, n / 2, mod);
	return a * powmod(a, n - 1, mod) % mod;
}

signed main() {
	int i, j;
	
	fact[0] = 1;
	finv[0] = 1;
	rep(i, 100000) {
		fact[i + 1] = (i + 1) * fact[i] % mod;
		finv[i + 1] = powmod(fact[i + 1], mod - 2, mod);
	}
	
	cin >> n;
	rep(i, n) cin >> a[i];
	
	vector<int> pos6;
	pos6.push_back(-1);
	rep(i, n) if (a[i] == 6) { pos6.push_back(i); }
	pos6.push_back(n);
	
	int ans = 1;
	
	rep(i, (int)pos6.size() - 1) {
		int red = 0, blue = 0;
		for (j = pos6[i] + 1; j < pos6[i + 1]; j++) {
			if (a[j] % 2 == 0) { red++; }
			if (a[j] % 3 == 0) { blue++; }
		}
		ans *= fact[red + blue];
		ans *= finv[red]; ans %= mod;
		ans *= finv[blue]; ans %= mod;
	}
	
	int white = 0;
	rep(i, n) {
		if (a[i] % 2 != 0 && a[i] % 3 != 0) { white++; }
	}
	for (i = n - white + 1; i <= n; i++) { ans *= i; ans %= mod; }
	
	cout << ans << endl;
	return 0;
}
accuracy: 0.04225352112676056
time_ms: 60
memory_kb: 4672
final_rank: 14

code_snippet: /*
考えたこと：
(1) 2の倍数同士はswapできない
(2) 3の倍数同士はswapできない
それ以外はswapできる。
(1) だけなら、偶数を赤、奇数を白としたときに、赤の相対順序が固定化されて、それ以外は自由。
(2) を入れるなら、2の倍数は赤、3の倍数は青、ただし6は紫で、それ以外は白とすると
・白はあとから自由に挿入できるので、以降 0 個として本質を失わない。
・(赤+青) 紫 (赤+青) の構造を考えると、左側と右側で独立に数えられる。
・赤+青の構造では、赤の相対順と青の相対順が固定化され、それ以外は自由なので、重複数え上げ。
計算量は O(N) になる。

実装上の注意：AtCoder Libraryはそのままでは利用できない
*/

#include <iostream>
#define rep(i, n) for(i = 0; i < n; i++)
#define int long long
using namespace std;

int mod = 998244353;
int n;
int a[100000];
int fact[100001];
int finv[100001];

int powmod(int a, int n, int mod) {
	if (n == 0) return 1;
	if (n % 2 == 0) return powmod((a * a) % mod, n / 2, mod);
	return a * powmod(a, n - 1, mod) % mod;
}

signed main() {
	int i;
	
	fact[0] = 1;
	finv[0] = 1;
	rep(i, 100000) {
		fact[i + 1] = (i + 1) * fact[i] % mod;
		finv[i + 1] = powmod(fact[i + 1], mod - 2, mod);
	}
	
	cin >> n;
	rep(i, n) cin >> a[i];
	
	int pos6 = n;
	rep(i, n) if (a[i] == 6) { pos6 = i; break; }
	
	int ans = 1;
	int red = 0, blue = 0;
	rep(i, pos6) {
		if (a[i] % 2 == 0) { red++; }
		if (a[i] % 3 == 0) { blue++; }
	}
	
	ans *= fact[red + blue];
	ans *= finv[red]; ans %= mod;
	ans *= finv[blue]; ans %= mod;
	
	red = 0;
	blue = 0;
	for (i = pos6 + 1; i < n; i++) {
		if (a[i] % 2 == 0) { red++; }
		if (a[i] % 3 == 0) { blue++; }
	}
	
	ans *= fact[red + blue]; ans %= mod;
	ans *= finv[red]; ans %= mod;
	ans *= finv[blue]; ans %= mod;
	
	int white = 0;
	rep(i, n) {
		if (a[i] % 2 != 0 && a[i] % 3 != 0) { white++; }
	}
	for (i = n - white + 1; i <= n; i++) { ans *= i; ans %= mod; }
	
	cout << ans << endl;
	return 0;
}
accuracy: 0.028169014084507043
time_ms: 60
memory_kb: 4616
final_rank: 18

code_snippet: /*
考えたこと：
(1) 2の倍数同士はswapできない
(2) 3の倍数同士はswapできない
それ以外はswapできる。
(1) だけなら、偶数を赤、奇数を白としたときに、赤の相対順序が固定化されて、それ以外は自由。
(2) を入れるなら、2の倍数は赤、3の倍数は青、ただし6は紫で、それ以外は白とすると
・白はあとから自由に挿入できるので、以降 0 個として本質を失わない。
・(赤+青) 紫 (赤+青) の構造を考えると、左側と右側で独立に数えられる。
・赤+青の構造では、赤の相対順と青の相対順が固定化され、それ以外は自由なので、重複数え上げ。
計算量は O(N) になる。

実装上の注意：AtCoder Libraryはそのままでは利用できない
*/

#include <iostream>
#define rep(i, n) for(i = 0; i < n; i++)
#define int long long
using namespace std;

int mod = 998244353;
int n;
int a[100000];
int fact[100001];
int finv[100001];

int powmod(int a, int n, int mod) {
	if (n == 0) return 1;
	if (n % 2 == 0) return powmod((a * a) % mod, n / 2, mod);
	return a * powmod(a, n - 1, mod) % mod;
}

signed main() {
	int i;
	
	fact[0] = 1;
	finv[0] = 1;
	rep(i, 100000) {
		fact[i + 1] = (i + 1) * fact[i] % mod;
		finv[i + 1] = powmod(fact[i + 1], mod - 2, mod);
	}
	
	cin >> n;
	rep(i, n) cin >> a[i];
	
	int pos6 = n;
	rep(i, n) if (a[i] == 6) { pos6 = i; break; }
	
	int ans = 1;
	int red = 0, blue = 0;
	rep(i, pos6) {
		if (a[i] % 2 == 0) { red++; }
		if (a[i] % 3 == 0) { blue++; }
	}
	
	ans *= fact[red + blue];
	ans *= finv[red]; ans %= mod;
	ans *= finv[blue]; ans %= mod;
	
	red = 0;
	blue = 0;
	for (i = pos6 + 1; i < n; i++) {
		if (a[i] % 2 == 0) { red++; }
		if (a[i] % 3 == 0) { blue++; }
	}
	
	ans *= fact[red + blue];
	ans *= finv[red]; ans %= mod;
	ans *= finv[blue]; ans %= mod;
	
	int white = 0;
	rep(i, n) {
		if (a[i] % 2 != 0 && a[i] % 3 != 0) { white++; }
	}
	for (i = n - white + 1; i <= n; i++) { ans *= i; ans %= mod; }
	
	cout << ans << endl;
	return 0;
}
accuracy: 0.028169014084507043
time_ms: 60
memory_kb: 4652
final_rank: 19

code_snippet: /*
考えたこと：
(1) 2の倍数同士はswapできない
(2) 3の倍数同士はswapできない
それ以外はswapできる。
(1) だけなら、偶数を赤、奇数を白としたときに、赤の相対順序が固定化されて、それ以外は自由。
(2) を入れるなら、2の倍数は赤、3の倍数は青、ただし6は紫で、それ以外は白とすると
・白はあとから自由に挿入できるので、以降 0 個として本質を失わない。
・(赤+青) 紫 (赤+青) の構造を考えると、左側と右側で独立に数えられる。
・赤+青の構造では、赤の相対順と青の相対順が固定化され、それ以外は自由なので、重複数え上げ。
計算量は O(N) になる。

実装上の注意：AtCoder Libraryはそのままでは利用できない
*/

#include <iostream>
#define rep(i, n) for(i = 0; i < n; i++)
#define int long long
using namespace std;

int mod = 998244353;
int n;
int a[100000];
int fact[100001];
int finv[100001];

int powmod(int a, int n, int mod) {
	if (n == 0) return 1;
	if (n % 2 == 0) return powmod((a * a) % mod, n / 2, mod);
	return a * powmod(a, n - 1, mod) % mod;
}

signed main() {
	int i;
	
	fact[0] = 1;
	finv[0] = 1;
	rep(i, 100000) {
		fact[i + 1] = (i + 1) * fact[i] % mod;
		finv[i + 1] = powmod(i + 1, mod - 2, mod);
	}
	
	cin >> n;
	rep(i, n) cin >> a[i];
	
	int pos6 = n;
	rep(i, n) if (a[i] == 6) { pos6 = i; break; }
	
	int ans = 1;
	int red = 0, blue = 0;
	rep(i, pos6) {
		if (a[i] % 2 == 0) { red++; }
		if (a[i] % 3 == 0) { blue++; }
	}
	
	ans *= fact[red + blue];
	ans *= finv[red]; ans %= mod;
	ans *= finv[blue]; ans %= mod;
	
	red = 0;
	blue = 0;
	for (i = pos6 + 1; i < n; i++) {
		if (a[i] % 2 == 0) { red++; }
		if (a[i] % 3 == 0) { blue++; }
	}
	
	ans *= fact[red + blue];
	ans *= finv[red]; ans %= mod;
	ans *= finv[blue]; ans %= mod;
	
	int white = 0;
	rep(i, n) {
		if (a[i] % 2 != 0 && a[i] % 3 != 0) { white++; }
	}
	for (i = n - white + 1; i <= n; i++) { ans *= i; ans %= mod; }
	
	cout << ans << endl;
	return 0;
}
accuracy: 0.028169014084507043
time_ms: 60
memory_kb: 4656
final_rank: 20

code_snippet: #include<bits/stdc++.h>
namespace {
using namespace std;

#include <cassert>
#include <numeric>
#include <type_traits>

#ifdef _MSC_VER
#include <intrin.h>
#endif


#include <utility>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

constexpr long long safe_mod(long long x, long long m) {
    x %= m;
    if (x < 0) x += m;
    return x;
}

struct barrett {
    unsigned int _m;
    unsigned long long im;

    explicit barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}

    unsigned int umod() const { return _m; }

    unsigned int mul(unsigned int a, unsigned int b) const {

        unsigned long long z = a;
        z *= b;
#ifdef _MSC_VER
        unsigned long long x;
        _umul128(z, im, &x);
#else
        unsigned long long x =
            (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
        unsigned int v = (unsigned int)(z - x * _m);
        if (_m <= v) v += _m;
        return v;
    }
};

constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
    if (m == 1) return 0;
    unsigned int _m = (unsigned int)(m);
    unsigned long long r = 1;
    unsigned long long y = safe_mod(x, m);
    while (n) {
        if (n & 1) r = (r * y) % _m;
        y = (y * y) % _m;
        n >>= 1;
    }
    return r;
}

constexpr bool is_prime_constexpr(int n) {
    if (n <= 1) return false;
    if (n == 2 || n == 7 || n == 61) return true;
    if (n % 2 == 0) return false;
    long long d = n - 1;
    while (d % 2 == 0) d /= 2;
    constexpr long long bases[3] = {2, 7, 61};
    for (long long a : bases) {
        long long t = d;
        long long y = pow_mod_constexpr(a, t, n);
        while (t != n - 1 && y != 1 && y != n - 1) {
            y = y * y % n;
            t <<= 1;
        }
        if (y != n - 1 && t % 2 == 0) {
            return false;
        }
    }
    return true;
}
template <int n> constexpr bool is_prime = is_prime_constexpr(n);

constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
    a = safe_mod(a, b);
    if (a == 0) return {b, 0};

    long long s = b, t = a;
    long long m0 = 0, m1 = 1;

    while (t) {
        long long u = s / t;
        s -= t * u;
        m0 -= m1 * u;  // |m1 * u| <= |m1| * s <= b


        auto tmp = s;
        s = t;
        t = tmp;
        tmp = m0;
        m0 = m1;
        m1 = tmp;
    }
    if (m0 < 0) m0 += b / s;
    return {s, m0};
}

constexpr int primitive_root_constexpr(int m) {
    if (m == 2) return 1;
    if (m == 167772161) return 3;
    if (m == 469762049) return 3;
    if (m == 754974721) return 11;
    if (m == 998244353) return 3;
    int divs[20] = {};
    divs[0] = 2;
    int cnt = 1;
    int x = (m - 1) / 2;
    while (x % 2 == 0) x /= 2;
    for (int i = 3; (long long)(i)*i <= x; i += 2) {
        if (x % i == 0) {
            divs[cnt++] = i;
            while (x % i == 0) {
                x /= i;
            }
        }
    }
    if (x > 1) {
        divs[cnt++] = x;
    }
    for (int g = 2;; g++) {
        bool ok = true;
        for (int i = 0; i < cnt; i++) {
            if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
                ok = false;
                break;
            }
        }
        if (ok) return g;
    }
}
template <int m> constexpr int primitive_root = primitive_root_constexpr(m);

unsigned long long floor_sum_unsigned(unsigned long long n,
                                      unsigned long long m,
                                      unsigned long long a,
                                      unsigned long long b) {
    unsigned long long ans = 0;
    while (true) {
        if (a >= m) {
            ans += n * (n - 1) / 2 * (a / m);
            a %= m;
        }
        if (b >= m) {
            ans += n * (b / m);
            b %= m;
        }

        unsigned long long y_max = a * n + b;
        if (y_max < m) break;
        n = (unsigned long long)(y_max / m);
        b = (unsigned long long)(y_max % m);
        std::swap(m, a);
    }
    return ans;
}

}  // namespace internal

}  // namespace atcoder


#include <cassert>
#include <numeric>
#include <type_traits>

namespace atcoder {

namespace internal {

#ifndef _MSC_VER
template <class T>
using is_signed_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value ||
                                  std::is_same<T, __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int128 =
    typename std::conditional<std::is_same<T, __uint128_t>::value ||
                                  std::is_same<T, unsigned __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using make_unsigned_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value,
                              __uint128_t,
                              unsigned __int128>;

template <class T>
using is_integral = typename std::conditional<std::is_integral<T>::value ||
                                                  is_signed_int128<T>::value ||
                                                  is_unsigned_int128<T>::value,
                                              std::true_type,
                                              std::false_type>::type;

template <class T>
using is_signed_int = typename std::conditional<(is_integral<T>::value &&
                                                 std::is_signed<T>::value) ||
                                                    is_signed_int128<T>::value,
                                                std::true_type,
                                                std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<(is_integral<T>::value &&
                               std::is_unsigned<T>::value) ||
                                  is_unsigned_int128<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<
    is_signed_int128<T>::value,
    make_unsigned_int128<T>,
    typename std::conditional<std::is_signed<T>::value,
                              std::make_unsigned<T>,
                              std::common_type<T>>::type>::type;

#else

template <class T> using is_integral = typename std::is_integral<T>;

template <class T>
using is_signed_int =
    typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<is_integral<T>::value &&
                                  std::is_unsigned<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<is_signed_int<T>::value,
                                              std::make_unsigned<T>,
                                              std::common_type<T>>::type;

#endif

template <class T>
using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;

template <class T>
using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;

template <class T> using to_unsigned_t = typename to_unsigned<T>::type;

}  // namespace internal

}  // namespace atcoder


namespace atcoder {

namespace internal {

struct modint_base {};
struct static_modint_base : modint_base {};

template <class T> using is_modint = std::is_base_of<modint_base, T>;
template <class T> using is_modint_t = std::enable_if_t<is_modint<T>::value>;

}  // namespace internal

template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
struct static_modint : internal::static_modint_base {
    using mint = static_modint;

  public:
    static constexpr int mod() { return m; }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    static_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    static_modint(T v) {
        long long x = (long long)(v % (long long)(umod()));
        if (x < 0) x += umod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    static_modint(T v) {
        _v = (unsigned int)(v % umod());
    }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v -= rhs._v;
        if (_v >= umod()) _v += umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        unsigned long long z = _v;
        z *= rhs._v;
        _v = (unsigned int)(z % umod());
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        if (prime) {
            assert(_v);
            return pow(umod() - 2);
        } else {
            auto eg = internal::inv_gcd(_v, m);
            assert(eg.first == 1);
            return eg.second;
        }
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static constexpr unsigned int umod() { return m; }
    static constexpr bool prime = internal::is_prime<m>;
};

template <int id> struct dynamic_modint : internal::modint_base {
    using mint = dynamic_modint;

  public:
    static int mod() { return (int)(bt.umod()); }
    static void set_mod(int m) {
        assert(1 <= m);
        bt = internal::barrett(m);
    }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    dynamic_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        long long x = (long long)(v % (long long)(mod()));
        if (x < 0) x += mod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        _v = (unsigned int)(v % mod());
    }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v += mod() - rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        _v = bt.mul(_v, rhs._v);
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        auto eg = internal::inv_gcd(_v, mod());
        assert(eg.first == 1);
        return eg.second;
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static internal::barrett bt;
    static unsigned int umod() { return bt.umod(); }
};
template <int id> internal::barrett dynamic_modint<id>::bt(998244353);

using modint998244353 = static_modint<998244353>;
using modint1000000007 = static_modint<1000000007>;
using modint = dynamic_modint<-1>;

namespace internal {

template <class T>
using is_static_modint = std::is_base_of<internal::static_modint_base, T>;

template <class T>
using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;

template <class> struct is_dynamic_modint : public std::false_type {};
template <int id>
struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};

template <class T>
using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;

}  // namespace internal

}  // namespace atcoder

using namespace atcoder;
#define rep(i,n) for(int i = 0; i < (int)(n); i++)
#define rrep(i,n) for(int i = (int)(n) - 1; i >= 0; i--)
#define all(x) begin(x), end(x)
#define rall(x) rbegin(x), rend(x)
template<class T> bool chmax(T& a, const T& b) { if (a < b) { a = b; return true; } else return false; }
template<class T> bool chmin(T& a, const T& b) { if (b < a) { a = b; return true; } else return false; }
using ll = long long;
using P = pair<int,int>;
using VI = vector<int>;
using VVI = vector<VI>;
using VL = vector<ll>;
using VVL = vector<VL>;
using mint = modint998244353;

constexpr int FACT_SIZE = 1000000;
mint Fact[FACT_SIZE + 1];
mint iFact[FACT_SIZE + 1];
const auto fact_init = [] {
    Fact[0] = mint::raw(1);
    for(int i = 1; i <= FACT_SIZE; ++i) {
        Fact[i] = Fact[i-1] * i;
    }
    iFact[FACT_SIZE] = Fact[FACT_SIZE].inv();
    for(int i = FACT_SIZE; i; --i) {
        iFact[i-1] = iFact[i] * i;
    }
    return false;
}();

mint comb(int n, int k) {
    if (k == 0) return mint::raw(1);
    assert(n >= 0 && k >= 0);
    if (k > n) return mint::raw(0);
    return Fact[n] * iFact[n - k] * iFact[k];
}

mint icomb(int n, int k) {
    return iFact[n] * Fact[n - k] * Fact[k];
}

mint fact(int n) {return Fact[n];}
mint perm(int n, int k) {
    assert(0 <= n);
    return Fact[n] * iFact[n - k];
}

} int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int n;
  cin >> n;
  VI a(n);
  rep(i, n) cin >> a[i];
  int c2 = 0, c3 = 0, c1 = 0, c5 = 0, c7 = 0;
  mint ans = 1;
  rep(i, n) {
    int x = a[i];
    if (x == 6) {
      ans *= comb(c2 + c3, c2);
      c2 = c3 = 0;
    } else if (x % 2 == 0) c2++;
    else if (x % 3 == 0) c3++;
    else if (x == 1) c1++;
    else if (x == 5) c5++;
    else c7++;
  }
  ans *= comb(c2 + c3, c2);
  ans *= Fact[n] * iFact[c1] * iFact[c5] * iFact[c7] * iFact[n - c1 - c5 - c7];
  cout << ans.val() << '\n';
}
accuracy: 1
time_ms: 10
memory_kb: 11388
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;

struct iofast_t {
    iofast_t() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
    }
} iofast;

struct uns_t {} uns;
template <typename Element, typename Head, typename ...Args>
auto vec(Element init, Head arg, Args ...args) {
    if constexpr (sizeof...(Args) == 0) return vector(arg, init);
    else return vector(arg, vec(init, args...));
}
template <typename Element, typename Head, typename ...Args>
auto vec(uns_t, Head arg, Args ...args) {
    return vec(Element(), arg, args...);
}

template <typename Container>
auto distance(const Container &c, decltype(begin(c)) iter) {
    return distance(begin(c), iter);
}

template <typename RIter, typename Compare = less<typename iterator_traits<RIter>::value_type>>
auto isort(RIter first, RIter last, Compare comp = Compare()) {
    vector<int> i(distance(first, last));
    iota(begin(i), end(i), 0);
    sort(begin(i), end(i), [&](auto x, auto y) {
        return comp(*(first + x), *(first + y));
    });
    return i;
}

template <typename, template <typename> typename, typename = void_t<>>
struct detect : false_type {};
template <typename T, template <typename> typename Check>
struct detect<T, Check, void_t<Check<T>>> : true_type {};
template <typename T, template <typename> typename Check>
constexpr inline bool detect_v = detect<T, Check>::value;

template <typename T>
using has_member_sort = decltype(declval<T>().sort());

template <typename Container, typename Compare = less<typename Container::value_type>>
auto sorted(Container c, Compare comp = Compare()) {
    if constexpr (detect_v<Container, has_member_sort>) {
        c.sort(comp);
        return c;
    }
    else {
        sort(begin(c), end(c), comp);
        return c;
    }
}

template <typename Container, typename Compare = equal_to<typename Container::value_type>>
auto uniqued(Container c, Compare comp = Compare()) {
    c.erase(unique(begin(c), end(c), comp), end(c));
    return c;
}

template <typename T, typename Compare = less<T>>
T &chmin(T &l, T r, Compare &&f = less<T>()) { return l = min(l, r, f); }
template <typename T, typename Compare = less<T>>
T &chmax(T &l, T r, Compare &&f = less<T>()) { return l = max(l, r, f); }


#include <cassert>
#include <numeric>
#include <type_traits>

#ifdef _MSC_VER
#include <intrin.h>
#endif


#include <utility>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

constexpr long long safe_mod(long long x, long long m) {
    x %= m;
    if (x < 0) x += m;
    return x;
}

struct barrett {
    unsigned int _m;
    unsigned long long im;

    explicit barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}

    unsigned int umod() const { return _m; }

    unsigned int mul(unsigned int a, unsigned int b) const {

        unsigned long long z = a;
        z *= b;
#ifdef _MSC_VER
        unsigned long long x;
        _umul128(z, im, &x);
#else
        unsigned long long x =
            (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
        unsigned int v = (unsigned int)(z - x * _m);
        if (_m <= v) v += _m;
        return v;
    }
};

constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
    if (m == 1) return 0;
    unsigned int _m = (unsigned int)(m);
    unsigned long long r = 1;
    unsigned long long y = safe_mod(x, m);
    while (n) {
        if (n & 1) r = (r * y) % _m;
        y = (y * y) % _m;
        n >>= 1;
    }
    return r;
}

constexpr bool is_prime_constexpr(int n) {
    if (n <= 1) return false;
    if (n == 2 || n == 7 || n == 61) return true;
    if (n % 2 == 0) return false;
    long long d = n - 1;
    while (d % 2 == 0) d /= 2;
    constexpr long long bases[3] = {2, 7, 61};
    for (long long a : bases) {
        long long t = d;
        long long y = pow_mod_constexpr(a, t, n);
        while (t != n - 1 && y != 1 && y != n - 1) {
            y = y * y % n;
            t <<= 1;
        }
        if (y != n - 1 && t % 2 == 0) {
            return false;
        }
    }
    return true;
}
template <int n> constexpr bool is_prime = is_prime_constexpr(n);

constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
    a = safe_mod(a, b);
    if (a == 0) return {b, 0};

    long long s = b, t = a;
    long long m0 = 0, m1 = 1;

    while (t) {
        long long u = s / t;
        s -= t * u;
        m0 -= m1 * u;  // |m1 * u| <= |m1| * s <= b


        auto tmp = s;
        s = t;
        t = tmp;
        tmp = m0;
        m0 = m1;
        m1 = tmp;
    }
    if (m0 < 0) m0 += b / s;
    return {s, m0};
}

constexpr int primitive_root_constexpr(int m) {
    if (m == 2) return 1;
    if (m == 167772161) return 3;
    if (m == 469762049) return 3;
    if (m == 754974721) return 11;
    if (m == 998244353) return 3;
    int divs[20] = {};
    divs[0] = 2;
    int cnt = 1;
    int x = (m - 1) / 2;
    while (x % 2 == 0) x /= 2;
    for (int i = 3; (long long)(i)*i <= x; i += 2) {
        if (x % i == 0) {
            divs[cnt++] = i;
            while (x % i == 0) {
                x /= i;
            }
        }
    }
    if (x > 1) {
        divs[cnt++] = x;
    }
    for (int g = 2;; g++) {
        bool ok = true;
        for (int i = 0; i < cnt; i++) {
            if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
                ok = false;
                break;
            }
        }
        if (ok) return g;
    }
}
template <int m> constexpr int primitive_root = primitive_root_constexpr(m);

unsigned long long floor_sum_unsigned(unsigned long long n,
                                      unsigned long long m,
                                      unsigned long long a,
                                      unsigned long long b) {
    unsigned long long ans = 0;
    while (true) {
        if (a >= m) {
            ans += n * (n - 1) / 2 * (a / m);
            a %= m;
        }
        if (b >= m) {
            ans += n * (b / m);
            b %= m;
        }

        unsigned long long y_max = a * n + b;
        if (y_max < m) break;
        n = (unsigned long long)(y_max / m);
        b = (unsigned long long)(y_max % m);
        std::swap(m, a);
    }
    return ans;
}

}  // namespace internal

}  // namespace atcoder


#include <cassert>
#include <numeric>
#include <type_traits>

namespace atcoder {

namespace internal {

#ifndef _MSC_VER
template <class T>
using is_signed_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value ||
                                  std::is_same<T, __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int128 =
    typename std::conditional<std::is_same<T, __uint128_t>::value ||
                                  std::is_same<T, unsigned __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using make_unsigned_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value,
                              __uint128_t,
                              unsigned __int128>;

template <class T>
using is_integral = typename std::conditional<std::is_integral<T>::value ||
                                                  is_signed_int128<T>::value ||
                                                  is_unsigned_int128<T>::value,
                                              std::true_type,
                                              std::false_type>::type;

template <class T>
using is_signed_int = typename std::conditional<(is_integral<T>::value &&
                                                 std::is_signed<T>::value) ||
                                                    is_signed_int128<T>::value,
                                                std::true_type,
                                                std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<(is_integral<T>::value &&
                               std::is_unsigned<T>::value) ||
                                  is_unsigned_int128<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<
    is_signed_int128<T>::value,
    make_unsigned_int128<T>,
    typename std::conditional<std::is_signed<T>::value,
                              std::make_unsigned<T>,
                              std::common_type<T>>::type>::type;

#else

template <class T> using is_integral = typename std::is_integral<T>;

template <class T>
using is_signed_int =
    typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<is_integral<T>::value &&
                                  std::is_unsigned<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<is_signed_int<T>::value,
                                              std::make_unsigned<T>,
                                              std::common_type<T>>::type;

#endif

template <class T>
using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;

template <class T>
using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;

template <class T> using to_unsigned_t = typename to_unsigned<T>::type;

}  // namespace internal

}  // namespace atcoder


namespace atcoder {

namespace internal {

struct modint_base {};
struct static_modint_base : modint_base {};

template <class T> using is_modint = std::is_base_of<modint_base, T>;
template <class T> using is_modint_t = std::enable_if_t<is_modint<T>::value>;

}  // namespace internal

template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
struct static_modint : internal::static_modint_base {
    using mint = static_modint;

  public:
    static constexpr int mod() { return m; }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    static_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    static_modint(T v) {
        long long x = (long long)(v % (long long)(umod()));
        if (x < 0) x += umod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    static_modint(T v) {
        _v = (unsigned int)(v % umod());
    }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v -= rhs._v;
        if (_v >= umod()) _v += umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        unsigned long long z = _v;
        z *= rhs._v;
        _v = (unsigned int)(z % umod());
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        if (prime) {
            assert(_v);
            return pow(umod() - 2);
        } else {
            auto eg = internal::inv_gcd(_v, m);
            assert(eg.first == 1);
            return eg.second;
        }
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static constexpr unsigned int umod() { return m; }
    static constexpr bool prime = internal::is_prime<m>;
};

template <int id> struct dynamic_modint : internal::modint_base {
    using mint = dynamic_modint;

  public:
    static int mod() { return (int)(bt.umod()); }
    static void set_mod(int m) {
        assert(1 <= m);
        bt = internal::barrett(m);
    }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    dynamic_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        long long x = (long long)(v % (long long)(mod()));
        if (x < 0) x += mod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        _v = (unsigned int)(v % mod());
    }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v += mod() - rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        _v = bt.mul(_v, rhs._v);
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        auto eg = internal::inv_gcd(_v, mod());
        assert(eg.first == 1);
        return eg.second;
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static internal::barrett bt;
    static unsigned int umod() { return bt.umod(); }
};
template <int id> internal::barrett dynamic_modint<id>::bt(998244353);

using modint998244353 = static_modint<998244353>;
using modint1000000007 = static_modint<1000000007>;
using modint = dynamic_modint<-1>;

namespace internal {

template <class T>
using is_static_modint = std::is_base_of<internal::static_modint_base, T>;

template <class T>
using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;

template <class> struct is_dynamic_modint : public std::false_type {};
template <int id>
struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};

template <class T>
using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;

}  // namespace internal

}  // namespace atcoder

using mint = atcoder::modint998244353;

int main() {
    constexpr auto lim = 9;

    int n; cin >> n;
    auto a = vec<int>(uns, n);
    for (auto &e : a) cin >> e;

    auto f = vec<mint>(uns, n + 1);
    auto g = vec<mint>(uns, n + 1);

    f[0] = g[0] = 1;
    for (int i = 1; i <= n; ++i) {
        f[i] = f[i - 1] * i;
        g[i] = 1 / f[i];
    }

    auto comb = [&](int n, int r) {
        return f[n] * g[r] * g[n - r];
    };

    auto b = vec<int>(uns, 0);
    for (auto v : a) {
        if (v % 2 == 0 || v % 3 == 0) {
            b.push_back(v);
        }
    }

    mint sub = 1;

    int l = 0, r = 0;
    int even = 0, odd = 0;
    while (r <= size(b)) {
        if (r < size(b) && b[r] != 6) {
            even += (b[r] % 2 == 0);
            odd += (b[r] % 3 == 0);
            ++r;
            continue;
        }

        sub *= comb(even + odd, even);

        even = 0;
        odd = 0;
        l = ++r;
    }

    mint ans = sub;

    int rem = n;
    for (int i = 1; i <= lim; ++i) {
        if (i % 2 == 0 || i % 3 == 0) {
            continue;
        }
        int c = count(begin(a), end(a), i);
        ans *= comb(rem, c); rem -= c;
    }

    cout << ans.val() << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 4936
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;
template<const int MOD> struct modint{
    long long val;
    modint(): val(0) {}
    modint(long long x){
        if(x < 0) val = x % MOD + MOD;
        else val = x % MOD;
    }
    modint(const modint &t){
        val = t.val;
    }
    modint& operator =(const modint m){
        val = m.val;
        return *this;
    }
    modint operator -(){
        return modint(-val);
    }
    modint& operator-=(const modint &m){
        val -= m.val;
        if(val < 0) val += MOD;
        return *this;
    }
    modint& operator+=(const modint &m){
        val += m.val;
        if(val >= MOD) val -= MOD;
        return *this;
    }
    modint& operator*=(const modint &m){
        val *= m.val;
        val %= MOD;
        return *this;
    }
    modint& operator/=(modint m){
        *this *= m.inv();
        return *this;
    }
    modint inv(){
        long long x = 1, y = 0;
        long long a = val, b = MOD;
        while(b != 0){
            long long t = a / b;
            a -= t * b;
            x -= t * y;
            swap(a, b);
            swap(x, y);
        }
        x %= MOD;
        if(x < 0) x += MOD;
        return modint(x);
    }
    modint pow(long long k){
        long long res = 1;
        long long v = val;
        if(v == 0) return modint(0);
        while(k > 0){
            if(k & 1) res = res * v % MOD;
            v = v * v % MOD;
            k >>= 1;
    }
        return modint(res);
    }
    bool operator==(const modint &m){
        return val == m.val;
    }
    modint operator+(const modint &m){
        return modint(*this) += m;
    }
    modint operator-(const modint &m){
        return modint(*this) -= m;
    }
    modint operator*(const modint &m){
        return modint(*this) *= m;
    }
    modint operator/(const modint &m){
        return modint(*this) /= m;
    }
    bool operator!=(const modint &m){
        return modint(*this).val != m.val;
    }
    bool operator!=(const int &m){
        return modint(*this).val != m;
    }
};
const int MOD = 998244353;
using mint = modint<MOD>;
const int MAX = 410000;
mint fac[MAX], finv[MAX], inv[MAX];
//MAX < MOD
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;
        inv[i] = mint(MOD) - inv[MOD % i] * (MOD / i);
        finv[i] = finv[i - 1] * inv[i];
    }
}
mint 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];
}
int main(){
    int N;
    cin >> N;
    vector<int> A(N);
    for(int i = 0; i < N; i++) cin >> A[i];
    vector<vector<int>> p(10);
    for(int i = 0; i < N; i++){
        if(A[i] == 1) p[A[i]].push_back(i);
        if(A[i] % 2 == 0) p[2].push_back(i);
        if(A[i] % 3 == 0) p[3].push_back(i);
        if(A[i] % 5 == 0) p[5].push_back(i);
        if(A[i] % 7 == 0) p[7].push_back(i);
        if(A[i] == 6) p[6].push_back(i);
    }
    COMinit();
    p[6].push_back(N);
    p[2].push_back(N);
    p[3].push_back(N);
    mint ans = 1;
    int sum = 0;
    for(int i = 0; i < (int)p[6].size(); i++){
        if(i == 0){
            int ni = lower_bound(p[2].begin(), p[2].end(), p[6][i]) - p[2].begin();
            int san = lower_bound(p[3].begin(), p[3].end(), p[6][i]) - p[3].begin();
            ans *= COM(ni + san, san);
            sum += ni + san;
        }
        else{
            int ni = lower_bound(p[2].begin(), p[2].end(), p[6][i]) - upper_bound(p[2].begin(), p[2].end(), p[6][i - 1]);
            int san = lower_bound(p[3].begin(), p[3].end(), p[6][i]) - upper_bound(p[3].begin(), p[3].end(), p[6][i - 1]);
            ans *= COM(ni + san, san);
            sum += ni + san;
        }
    }
    sum += p[6].size() - 1;
    for(int i = 0; i < 10; i++){
        if(i % 2 == 0) continue;
        if(i % 3 == 0) continue;
        ans *= COM(sum + p[i].size(), sum);
        sum += p[i].size();
    }
    cout << ans.val << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 13896
final_rank: 8