#pragma region template #include #include using namespace std; using namespace atcoder; using mint = static_modint<998244353>; using vm = vector; using vvm = vector; ostream& operator<<(ostream& os, const mint& v) { os << v.val(); return os; } // clang-format off using ll = long long; using vl = vector; using vvl = vector; using vvvl = vector; using ld = long double; using vld = vector; using vvld = vector; using pll = pair; using vpll = vector; using vvpll = vector; using vi = vector; using vvi = vector; using vb = vector; using vvb = vector; using mll = map; using vs = vector; template using max_heap = priority_queue; template using min_heap = priority_queue, greater>; constexpr ll inf = 3001001000100100100LL; #define endl '\n' #define _overload(_1, _2, _3, name, ...) name #define rep(...) _overload(__VA_ARGS__, _rep, _rep2,)(__VA_ARGS__) #define repc(...) _overload(__VA_ARGS__, _repc, _repc2,)(__VA_ARGS__) #define repr(...) _overload(__VA_ARGS__, _repr, _repr2,)(__VA_ARGS__) #define reprc(...) _overload(__VA_ARGS__, _reprc, _reprc2,)(__VA_ARGS__) #define _rep(i,k,n) for(ll i=(k) , i##_xxxx=(n); i < i##_xxxx; ++i) #define _repc(i,k,n) for(ll i=(k) , i##_xxxx=(n); i <=i##_xxxx; ++i) #define _repr(i,k,n) for(ll i=(n)-1, i##_xxxx=(k); i >=i##_xxxx; --i) #define _reprc(i,k,n) for(ll i=(n) , i##_xxxx=(k); i >=i##_xxxx; --i) #define _rep2(i,n) _rep(i,0,n) #define _repc2(i,n) _repc(i,1,n) #define _repr2(i,n) _repr(i,0,n) #define _reprc2(i,n) _reprc(i,1,n) #define rall(o) rbegin(o), rend(o) #define all(o) begin(o), end(o) template ll sz(const C& c) { return static_cast(c.size()); } template common_type_t min(const T& a, const U& b){ return std::min>(a,b); } template common_type_t max(const T& a, const U& b){ return std::max>(a,b); } template bool chmax(T& m, const U& v){ if (m < v){ m = v; return true; } return false; } template bool chmin(T& m, const U& v){ if (v < m){ m = v; return true; } return false; } template common_type_t cdiv(const T& a, const U& b){ return (a + b - 1) / b; } template common_type_t rdiv(const T& a, const T& b){ return (a + b / 2) / b; } template string join(const T& v, const S& sep ){ stringstream ss; bool f = false; for (const auto& e : v){ if (f) ss << sep; f = true; ss << e;} return ss.str(); } template string join(const T& v, const S& sep, const U& ...args){ stringstream ss; bool f = false; for (const auto& c : v){ if (f) ss << sep; f = true; ss << join(c, args...); } return ss.str(); } template ostream& operator<<(ostream& os, const vector& seq){ os << '[' << join(seq, ",") << ']'; return os; } template ostream& operator<<(ostream& os, const vector>& seq){ os << '[' << join(seq, ",\n ") << ']'; return os; } template ostream& operator<<(ostream& os, const deque& seq){ os << '[' << join(seq, ",") << ']'; return os; } template ostream& operator<<(ostream& os, const set& seq){ os << '{' << join(seq, ",") << '}'; return os; } template ostream& operator<<(ostream& os, const unordered_set& seq){ os << '{' << join(seq, ",") << '}'; return os; } template ostream& operator<<(ostream& os, const map& seq){ os << '{'; bool f = false; for (const auto& e : seq){ if (f) os << ','; f = true; os << e.first << ":" << e.second; } os << '}'; return os; } template ostream& operator<<(ostream& os, const pair& pa){ os << '(' << pa.first << ',' << pa.second << ')'; return os; } #if LOCAL #define debug(...) _debug(__VA_ARGS__, __LINE__) #else #define debug(...) #endif void print() { std::cout << '\n'; } template void print(const S& a){ std::cout << a << '\n'; } template void _debug(const S& a){ std::cerr << "(L:" << std::setw(3) << a << ")\n"; } template void print(const S& a, const T&... args){ std::cout << a << ' '; print(args...); } template void _debug(const S& a, const T&... args){ std::cerr << a << ' '; _debug(args...); } struct setup_main { setup_main() { std::cin.tie(nullptr); std::ios::sync_with_stdio(false); std::cout << fixed << setprecision(15); } } setup_main_; // clang-format on #pragma endregion // 階乗 mint factorial(ll n) { if (n < 0) return 0; static vector fact = {1, 1}; while (sz(fact) <= n) fact.push_back(fact.back() * fact.size()); return fact[n]; } mint factorial_inv(ll n) { if (n < 0) return 0; static vector fact_inv; while (sz(fact_inv) <= n) fact_inv.push_back(1 / factorial(fact_inv.size())); return fact_inv[n]; } // 組み合わせ mint combination(ll n, ll k) { if (k > n or k < 0) return 0; return factorial(n) * factorial_inv(n - k) * factorial_inv(k); } // 順列 mint permutation(ll n, ll k) { if (k > n or k < 0) return 0; return factorial(n) * factorial_inv(n - k); } mint solve(ll N, vvl S) { mint ans = 0; unordered_set seen, seen_next; seen.insert(0); seen_next.reserve(3200000); seen.reserve(3200000); rep(i, N) { seen_next.clear(); for (ll v : seen) { rep(j, 6) { seen_next.insert(v + (1LL << 5 * S[i][j])); } } swap(seen, seen_next); } for (ll v : seen) { mint a = factorial(N); rep(i, 9) a *= factorial_inv((v >> i * 5) & 0b11111); ans += a; } return ans; } int main() { ll N; cin >> N; vvl S(N, vl(6)); rep(i, N) rep(j, 6) { cin >> S[i][j]; S[i][j]--; } print(solve(N, S)); }