Problem:
Chayas
Once upon a time, there were a number of chayas (teahouses) along one side of an east-west road in Yokohama. Although the total number of chayas is known, the information about their locations was considered to be lost totally.
Recently, a document describing the old townscapes of Yokohama has been found. The document contains a number of records on the order of the locations of chayas. Each record has information below on the order of the locations of three chayas, say $a$, $b$, and $c$.
Chaya $b$ was located between chayas $a$ and $c$. Note that there may have been other chayas between $a$ and $b$, or between $b$ and $c$. Also, note that chaya $a$ may have been located east of $c$ or west of $c$.
We want to know how many different orders of chayas along the road are consistent with all of these records in the recently found document. Note that, as the records may have some errors, there might exist no orders consistent with the records.
Input
The input consists of a single test case given in the following format.
$n$ $m$
$a_1$ $b_1$ $c_1$
.
.
.
$a_m$ $b_m$ $c_m$
Here, $n$ represents the number of chayas and m represents the number of records in the recently found document. $3 \leq n \leq 24$ and $1 \leq m \leq n \times (n - 1) \times (n - 2)/2$ hold. The chayas are numbered from $1$ to $n$.
Each of the following $m$ lines represents a record. The $i$-th of them contains three distinct integers $a_i$, $b_i$, and $c_i$, each between $1$ and $n$, inclusive. This says that chaya $b_i$ was located between chayas $a_i$ and $c_i$. No two records have the same information, that is, for any two different integers $i$ and $j$, the triple ($a_i$, $b_i$, $c_i$) is not equal to ($a_j, b_j, c_j$) nor ($c_j, b_j, a_j$).
Output
Output the number of different orders of the chayas, from east to west, consistent with all of the records modulo $998 244 353$ in a line. Note that $998 244 353 = 2^{23} \times 7 \times 17 + 1$ is a prime number.
Sample Input 1
5 4
1 2 4
2 3 5
3 2 4
1 3 2
Sample Output 1
4
Sample Input 2
4 2
3 1 4
1 4 3
Sample Output 2
0
For Sample Input 1, four orders, (1, 5, 3, 2, 4), (4, 2, 3, 1, 5), (4, 2, 3, 5, 1), and (5, 1, 3, 2, 4), are
consistent with the records.
For Sample Input 2, there are no consistent orders.

Submitted solutions:

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 sz(x) (int)(x).size()
#define all(x) x.begin(), x.end()
typedef pair<int, int> pii;
typedef vector<int> vi;
template <class T>
inline bool chmin(T& a, T b) {
  return ((a > b) ? (a = b, 1) : (0));
}
template <class T>
inline bool chmax(T& a, T b) {
  return ((a < b) ? (a = b, 1) : (0));
}
#define YesNo(f) cout << (f ? "Yes" : "No") << endl

void solve();
int main() {
  int T = 1;
  // cin >> T;
  while (T--) solve();
  return 0;
}
ll euclid(ll a, ll b, ll& x, ll& y) {
  if (!b) return x = 1, y = 0, a;
  ll d = euclid(b, a % b, y, x);
  return y -= a / b * x, d;
}
const ll mod = 998244353;  // change to something else
struct Mod {
  ll x;
  Mod(ll xx) : x(xx) {}
  Mod operator+(Mod b) { return Mod((x + b.x) % mod); }
  Mod operator-(Mod b) { return Mod((x - b.x + mod) % mod); }
  Mod operator*(Mod b) { return Mod((x * b.x) % mod); }
  Mod operator/(Mod b) { return *this * invert(b); }
  Mod invert(Mod a) {
    ll x, y, g = euclid(a.x, mod, x, y);
    assert(g == 1);
    return Mod((x + mod) % mod);
  }
  Mod operator^(ll e) {
    if (!e) return Mod(1);
    Mod r = *this ^ (e / 2);
    r = r * r;
    return e & 1 ? *this * r : r;
  }
};

void solve() {  // solver
  int N, M;
  cin >> N >> M;
  vector<vector<pii>> B_to_AC(N);

  rep(i, 0, M) {
    int a, b, c;
    cin >> a >> b >> c;
    a--, b--, c--;
    B_to_AC[b].push_back({a, c});
  }

  vector<uint> ng_A(1 << N), ng_B(1 << N);

  // bだけある
  rep(b, 0, N) {
    for (auto [a, c] : B_to_AC[b]) {
      int T = (1 << N) - 1;
      T &= ((1 << N) - 1) & ~(1 << a);
      T &= ((1 << N) - 1) & ~(1 << c);
      ng_A[T] |= 1 << b;
    }
  }

  // 高速ゼータ変換！
  rep(j, 0, N) rep(i, 0, 1 << N) if (~i >> j & 1) ng_A[i] |= ng_A[i | (1 << j)];

  // bだけない
  rep(b, 0, N) {
    for (auto [a, c] : B_to_AC[b]) {
      int T = 0;
      T |= 1 << a;
      T |= 1 << c;
      ng_B[T] |= 1 << b;
    }
  }
  rep(j, 0, N) rep(i, 0, 1 << N) if (i >> j & 1) ng_B[i] |= ng_B[i ^ (1 << j)];

  using Mint = Mod;
  vector<Mint> dp(1 << N, 0);
  vi is_ok(1 << N);
  rep(i, 0, 1 << N) {
    is_ok[i] = !((i & ng_A[i]) != 0 || ((~uint(i)) & ng_B[i]) != 0);
  }
  dp[0] = 1;

  rep(i, 0, 1 << N) {
    if (!is_ok[i] || dp[i].x == 0) continue;
    rep(j, 0, N) {
      if (i >> j & 1) continue;
      int ni = i | (1 << j);
      if (is_ok[ni]) dp[ni] = dp[ni] + dp[i];
    }
  }

  Mint ans = dp[(1 << N) - 1];
  cout << ans.x << endl;
  return;
}

/*
icpc-r-2023-e
むずかしい

a1-b1-(c1,a2)-b2-c2

(a1,a2)-(b1,b2)-c1-c2

解説みます
英語よわよわなのでむずかしい
作る場所の順番を決めるとbitdpができるようになる (dpのDAG性を確保してるんですね)
制約を集合でいいかえ
左から作っている集合をSとして

b in S && a,c nin S ->だめ
b nin S && a,c in S ->だめ
どっちかを満たした時点でSはだめになる

それぞれの条件で独立に満たすか判定をして問題を簡略化

2つの制約を独立にやることで高速ゼータ変換を適用


*/
accuracy: 1
time_ms: 1130
memory_kb: 331056
final_rank: 15

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

using ll = long long;

bool chmin(auto &a, auto b) { return a > b ? a = b, true : false; }
bool chmax(auto &a, auto b) { return a < b ? a = b, true : false; }

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int N, M;
    cin >> N >> M;
    vector<vector<pair<int, int>>> G(N), H(N);

    for(int i = 0; i < M; i++) {
        int a, b, c;
        cin >> a >> b >> c;
        a--, b--, c--;
        G[b].push_back(make_pair(a, c));
        H[a].push_back(make_pair(b, c));
        H[c].push_back(make_pair(b, a));
    }

    vector<int> memo(1 << N, -1);
    memo[0] = 1;
    constexpr int MOD = 998244353;
    auto f = [&](auto f, int s) -> int {
        if(memo[s] != -1) return memo[s];
        memo[s] = 0;
        for(int i = 0; i < N; i++) {
            int ok = (s >> i) & 1;
            for(const auto &[a, c] : G[i]) {
                if(!ok) break;
                ok &= ((s >> a) ^ (s >> c)) & 1;
            }
            for(const auto &[b, c] : H[i]) {
                if(!ok) continue;
                ok &= ((s >> c) | (~s >> b)) & 1;
            }
            if(ok) {
                memo[s] += f(f, s ^ (1 << i));
                if(memo[s] >= MOD) memo[s] -= MOD;
            }
        }
        return memo[s];
    };

    cout << f(f, (1 << N) - 1) << endl;
}
accuracy: 1
time_ms: 2900
memory_kb: 69160
final_rank: 7

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

using ll = long long;

bool chmin(auto &a, auto b) { return a > b ? a = b, true : false; }
bool chmax(auto &a, auto b) { return a < b ? a = b, true : false; }

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int N, M;
    cin >> N >> M;
    vector<vector<pair<int, int>>> G(N), H(N);

    for(int i = 0; i < M; i++) {
        int a, b, c;
        cin >> a >> b >> c;
        a--, b--, c--;
        G[b].push_back(make_pair(a, c));
        H[a].push_back(make_pair(b, c));
        H[c].push_back(make_pair(b, a));
    }

    vector<int> memo(1 << N, -1);
    memo[0] = 1;
    constexpr int MOD = 998244353;
    auto f = [&](auto f, int s) -> int {
        if(memo[s] != -1) return memo[s];
        memo[s] = 0;
        for(int i = 0; i < N; i++) {
            int ok = (s >> i) & 1;
            for(auto [a, c] : G[i]) {
                if(!ok) break;
                ok &= ((s >> a) ^ (s >> c)) & 1;
            }
            for(auto [b, c] : H[i]) {
                if(!ok) continue;
                ok &= ((s >> c) | (~s >> b)) & 1;
            }
            for(auto [b, a] : H[i]) {
                if(!ok) continue;
                ok &= ((s >> a) | (~s >> b)) & 1;
            }
            if(ok) {
                memo[s] += f(f, s ^ (1 << i));
                if(memo[s] >= MOD) memo[s] -= MOD;
            }
        }
        return memo[s];
    };

    cout << f(f, (1 << N) - 1) << endl;
}
accuracy: 1
time_ms: 3200
memory_kb: 69164
final_rank: 10

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (int i = 0; i < n; i++)
#define all(v) begin(v), end(v)
using ll = long long;
const int mod = 998244353;
bool cond[24][24][24];
ll dp[1 << 24];
int ng[1 << 24];
int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    int n, m;
    cin >> n >> m;
    rep(i, m) {
        int a, b, c;
        cin >> a >> b >> c;
        a--, b--, c--;
        ng[1 << a | 1 << c]++;
        ng[1 << b|1<<a|1<<c]--;
    }
    rep(j, n) rep(i, 1 << n) {
        if ((i >> j) & 1) ng[i] += ng[i - (1 << j)];
    }
    dp[0] = 1;
    for (int s = 1; s < (1 << n); s++) {
        if (ng[s] || ng[(1 << n) - 1 - s]) continue;
        rep(i, n) {
            if ((s >> i) & 1) {
                dp[s] += dp[s & ~(1 << i)];
            }
        }
        dp[s] %= mod;
    }
    cout << dp[(1 << n) - 1] << endl;
}
accuracy: 1
time_ms: 800
memory_kb: 199876
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (int i = 0; i < n; i++)
#define all(v) begin(v), end(v)
using ll = long long;
const int mod = 998244353;
bool cond[24][24][24];
ll dp[1 << 24];
int ng[1 << 24];
int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    int n, m;
    cin >> n >> m;
    rep(i, m) {
        int a, b, c;
        cin >> a >> b >> c;
        a--, b--, c--;
        ng[1 << a | 1 << c]++;
        ng[1 << b]++;
        ng[1 << a | 1 << b]--;
        ng[1 << c | 1 << b]--;
    }
    rep(j, n) rep(i, 1 << n) {
        if ((i >> j) & 1) ng[i] += ng[i - (1 << j)];
    }
    dp[0] = 1;
    for (int s = 1; s < (1 << n); s++) {
        if (ng[s] || ng[(1 << n) - 1 - s]) continue;
        rep(i, n) {
            if ((s >> i) & 1) {
                dp[s] += dp[s & ~(1 << i)];
            }
        }
        dp[s] %= mod;
    }
    cout << dp[(1 << n) - 1] << endl;
}
accuracy: 1
time_ms: 870
memory_kb: 199968
final_rank: 3

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define rep(i,n) for(int i=0;i<(int)(n);++i)
constexpr int mod=998244353;
int n,m;
vector<pair<int,int>>ac[24];
int dp[1<<24];
signed main(){
  cin.tie(0)->sync_with_stdio(0);
  cin>>n>>m;
  rep(i,m){
    int a,b,c;cin>>a>>b>>c,--a,--b,--c;
    ac[b].emplace_back(a,c);
  }
  dp[0]=1;
  for(int bit=1;bit<1<<n;++bit){
    rep(i,n){
      if(!(bit&(1<<i)))continue;
      int nbit=bit^(1<<i);
      bool ok=1;
      for(auto[a,c]:ac[i]){
        bool flag=0;
        if(nbit&(1<<a))flag=!flag;
        if(nbit&(1<<c))flag=!flag;
        if(!flag){
          ok=0;
          break;
        }
      }
      if(ok){
        dp[bit]+=dp[nbit];
        if(mod<=dp[bit])dp[bit]-=mod;
      }
    }
  }
  cout<<dp[(1<<n)-1]<<endl;
}
accuracy: 1
time_ms: 1980
memory_kb: 69120
final_rank: 1

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

using ll = long long;
const ll MOD = 998244353;

int main(){
    int n, m; cin >> n >> m;
    vector<vector<pair<int, int>>> center(n);
    vector<int> ng1(1 << n, 0); // a, c \in i となる条件 (a, j, c) があるかを求める 
    vector<int> ng2(1 << n, 0); // a, c \notin i となる条件 (a, j, c) があるかを求める
    int msk = (1 << n) - 1;
    for(int i = 0; i < m; ++i){
        int a, b, c; cin >> a >> b >> c, --a, --b, --c;
        ng1[(1 << a) | (1 << c)] |= 1 << b;
        ng2[msk ^ (1 << a) ^ (1 << c)] |= 1 << b;
    }

    // 高速ゼータ変換
    for (int j = 0; j < n; j++) {
        for (int i = 0; i < (1 << n); i++) {
            ng1[i | (1 << j)] |= ng1[i];
        }
    }
    for (int j = 0; j < n; j++) {
        for (int i = (1 << n)-1; i >= 0 ; i--) {
            ng2[i] |= ng2[i | (1 << j)];
        }
    }

    vector<ll> dp(1 << n, 0);
    dp[0] = 1;
    auto contain = [](int i, int j) -> bool {
        return ((i >> j) & 1);
    };
    for(int i = 0; i < 1 << n; ++i){
        for(int j = 0; j < n; ++j){
            if (!contain(i, j) && !contain(ng1[i], j) && !contain(ng2[i], j)) {
                dp[i | (1 << j)] = (dp[i | (1 << j)] + dp[i]) % MOD;
            }
        }
    }
    cout << dp[(1 << n) - 1] << endl;
}
accuracy: 1
time_ms: 2020
memory_kb: 265240
final_rank: 18

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

using ll = long long;
const ll MOD = 998244353;

int main(){
    int n, m; cin >> n >> m;
    vector<vector<pair<int, int>>> center(n);
    vector<int> ng1(1 << n, 0); // a, c \in i となる条件 (a, j, c) があるかを求める 
    vector<int> ng2(1 << n, 0); // a, c \notin i となる条件 (a, j, c) があるかを求める
    int msk = (1 << n) - 1;
    for(int i = 0; i < m; ++i){
        int a, b, c; cin >> a >> b >> c, --a, --b, --c;
        ng1[(1 << a) | (1 << c)] |= 1 << b;
        ng2[msk ^ (1 << a) ^ (1 << c)] |= 1 << b;
    }

    // 高速ゼータ変換
    for (int j = 0; j < n; j++) {
        for (int i = 0; i < (1 << n); i++) {
            ng1[i | (1 << j)] |= ng1[i];
        }
    }
        for (int j = 0; j < n; j++) {
        for (int i = (1 << n)-1; i >= 0 ; i--) {
            ng2[i] |= ng2[i | (1 << j)];
        }
    }

    vector<ll> dp(1 << n, 0);
    dp[0] = 1;
    auto contain = [](int i, int j) -> bool {
        return ((i >> j) & 1);
    };
    for(int i = 0; i < 1 << n; ++i){
        for(int j = 0; j < n; ++j){
            if (!contain(i, j) && !contain(ng1[i], j) && !contain(ng2[i], j)) {
                dp[i | (1 << j)] = (dp[i | (1 << j)] + dp[i]) % MOD;
            }
        }
    }
    cout << dp[(1 << n) - 1] << endl;
}
accuracy: 1
time_ms: 2030
memory_kb: 265380
final_rank: 19

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

using ll = long long;
const ll MOD = 998244353;

int main(){
    int n, m; cin >> n >> m;
    vector<vector<pair<int, int>>> center(n);
    vector<int> ng1(1 << n, 0); // a, c \in i となる条件 (a, j, c) があるかを求める 
    vector<int> ng2(1 << n, 0); // a, c \notin i となる条件 (a, j, c) があるかを求める
    int msk = (1 << n) - 1;
    for(int i = 0; i < m; ++i){
        int a, b, c; cin >> a >> b >> c, --a, --b, --c;
        ng1[(1 << a) | (1 << c)] |= 1 << b;
        ng2[msk ^ (1 << a) ^ (1 << c)] |= 1 << b;
    }

    // 高速ゼータ変換
    for (int j = 0; j < n; j++) {
        for (int i = 0; i < (1 << n); i++) {
            ng1[i | (1 << j)] |= ng1[i];
            ng2[i] |= ng2[i | (1 << j)];
        }
    }

    vector<ll> dp(1 << n, 0);
    dp[0] = 1;
    auto contain = [](int i, int j) -> bool {
        return ((i >> j) & 1);
    };
    for(int i = 0; i < 1 << n; ++i){
        for(int j = 0; j < n; ++j){
            if (!contain(i, j) && !contain(ng1[i], j) && !contain(ng2[i], j)) {
                dp[i | (1 << j)] = (dp[i | (1 << j)] + dp[i]) % MOD;
            }
        }
    }
    cout << dp[(1 << n) - 1] << endl;
}
accuracy: 1
time_ms: 1820
memory_kb: 265236
final_rank: 17

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

using ll = long long;
const ll MOD = 998244353;

int main(){
    int n, m; cin >> n >> m;
    vector<vector<pair<int, int>>> center(n);
    vector<int> ng1(1 << n, 0); // a, c \in i となる条件 (a, j, c) があるかを求める 
    vector<int> ng2(1 << n, 0); // a, c \notin i となる条件 (a, j, c) があるかを求める
    int msk = (1 << n) - 1;
    for(int i = 0; i < m; ++i){
        int a, b, c; cin >> a >> b >> c, --a, --b, --c;
        ng1[(1 << a) | (1 << c)] |= 1 << b;
        ng2[msk ^ (1 << a) ^ (1 << c)] |= 1 << b;
    }

    // 高速ゼータ変換
    for (int j = 0; j < n; j++) {
        for (int i = 0; i < (1 << n); i++) {
            ng1[i | (1 << j)] |= ng1[i];
            if ((i & (1 << j)) == 0) {
                
                ng2[i] |= ng2[i | (1 << j)];
            }
        }
    }

    vector<ll> dp(1 << n, 0);
    dp[0] = 1;
    auto contain = [](int i, int j) -> bool {
        return ((i >> j) & 1);
    };
    for(int i = 0; i < 1 << n; ++i){
        for(int j = 0; j < n; ++j){
            if (!contain(i, j) && !contain(ng1[i], j) && !contain(ng2[i], j)) {
                dp[i | (1 << j)] = (dp[i | (1 << j)] + dp[i]) % MOD;
            }
        }
    }
    cout << dp[(1 << n) - 1] << endl;
}
accuracy: 1
time_ms: 1800
memory_kb: 265172
final_rank: 16

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

using ll = long long;
const ll MOD = 998244353;

int main(){
    int n, m; cin >> n >> m;
    vector<vector<pair<int, int>>> center(n);
    vector<int> ng1(1 << n, 0); // a, c \in i となる条件 (a, j, c) があるかを求める 
    vector<int> ng2(1 << n, 0); // a, c \notin i となる条件 (a, j, c) があるかを求める
    int msk = (1 << n) - 1;
    for(int i = 0; i < m; ++i){
        int a, b, c; cin >> a >> b >> c, --a, --b, --c;
        ng1[(1 << a) | (1 << c)] |= 1 << b;
        ng2[msk ^ (1 << a) ^ (1 << c)] |= 1 << b;
    }

    // 高速ゼータ変換
    for (int j = 0; j < n; j++) {
        for (int i = 0; i < (1 << n); i++) {
            if ((i & (1 << j)) == 0) {
                ng1[i | (1 << j)] |= ng1[i];
                ng2[i] |= ng2[i | (1 << j)];
            }
        }
    }

    vector<ll> dp(1 << n, 0);
    dp[0] = 1;
    auto contain = [](int i, int j) -> bool {
        return ((i >> j) & 1);
    };
    for(int i = 0; i < 1 << n; ++i){
        for(int j = 0; j < n; ++j){
            if (!contain(i, j) && !contain(ng1[i], j) && !contain(ng2[i], j)) {
                dp[i | (1 << j)] = (dp[i | (1 << j)] + dp[i]) % MOD;
            }
        }
    }
    cout << dp[(1 << n) - 1] << endl;
}
accuracy: 1
time_ms: 1440
memory_kb: 265212
final_rank: 11

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

using ll = long long;
const ll MOD = 998244353;

int main(){
    int n, m; cin >> n >> m;
    vector<vector<pair<int, int>>> center(n);
    vector<int> ng1(1 << n, 0); // a, c \in i となる条件 (a, j, c) があるかを求める 
    vector<int> ng2(1 << n, 0); // a, c \notin i となる条件 (a, j, c) があるかを求める
    int msk = (1 << n) - 1;
    for(int i = 0; i < m; ++i){
        int a, b, c; cin >> a >> b >> c, --a, --b, --c;
        ng1[(1 << a) | (1 << c)] |= 1 << b;
        ng2[msk ^ (1 << a) ^ (1 << c)] |= 1 << b;
    }

    // 高速ゼータ変換
    for (int j = 0; j < n; j++) {
        for (int i = 0; i < (1 << n); i++) {
            if ((i & (1 << j)) == 0) {
                ng1[i | (1 << j)] |= ng1[i];
                ng2[i] |= ng2[i | (1 << j)];
            }
        }
    }

    vector<ll> dp(1 << n, 0);
    dp[0] = 1;
    auto contain = [](int i, int j) -> bool {
        return ((i >> j) & 1);
    };
    for(int i = 0; i < 1 << n; ++i){
        for(int j = 0; j < n; ++j){
            if (!contain(i, j) && !contain(ng1[i] | ng2[i], j)) {
                dp[i | (1 << j)] = (dp[i | (1 << j)] + dp[i]) % MOD;
            }
        }
    }
    cout << dp[(1 << n) - 1] << endl;
}
accuracy: 1
time_ms: 1490
memory_kb: 265236
final_rank: 13

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

using ll = long long;
const ll MOD = 998244353;

int main(){
    int n, m; cin >> n >> m;
    vector<vector<pair<int, int>>> center(n);
    vector<int> ng1(1 << n, 0); // a, c \in i となる条件 (a, j, c) があるかを求める 
    vector<int> ng2(1 << n, 0); // a, c \notin i となる条件 (a, j, c) があるかを求める
    int msk = (1 << n) - 1;
    for(int i = 0; i < m; ++i){
        int a, b, c; cin >> a >> b >> c, --a, --b, --c;
        ng1[(1 << a) | (1 << c)] |= 1 << b;
        ng2[msk ^ (1 << a) ^ (1 << c)] |= 1 << b;
    }

    // 高速ゼータ変換
    for (int j = 0; j < n; j++) {
        for (int i = 0; i < (1 << n); i++) {
            if ((i & (1 << j)) == 0) {
                ng1[i | (1 << j)] |= ng1[i];
                ng2[i] |= ng2[i | (1 << j)];
            }
        }
    }

    vector<ll> dp(1 << n, 0);
    dp[0] = 1;
    auto contain = [](int i, int j) -> bool {
        return ((i >> j) & 1);
    };
    for(int i = 0; i < 1 << n; ++i){
        for(int j = 0; j < n; ++j){
            if (!contain(i, j) && !contain(ng1[i] | ng2[i], j)) {
                dp[i | (1 << j)] = (dp[i | (1 << j)] + dp[i]) % MOD;
            }
        }
    }
    cout << dp[(1 << n) - 1] << endl;
}
accuracy: 1
time_ms: 1340
memory_kb: 265444
final_rank: 8

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

using ll = long long;
const ll MOD = 998244353;

int main(){
    int n, m; cin >> n >> m;
    vector<vector<pair<int, int>>> center(n);
    vector<int> dp1(1 << n, 0), dp2(1 << n, 0);
    int msk = (1 << n) - 1;
    for(int i = 0; i < m; ++i){
        int a, b, c; cin >> a >> b >> c, --a, --b, --c;
        dp1[(1 << a) | (1 << c)] |= 1 << b;
        dp2[msk ^ (1 << a) ^ (1 << c)] |= 1 << b;
    }

    // 高速ゼータ変換
    for (int j = 0; j < n; j++) {
        for (int i = 0; i < (1 << n); i++) {
            if ((i & (1 << j)) == 0) {
                dp1[i | (1 << j)] |= dp1[i];
                dp2[i] |= dp2[i | (1 << j)];
            }
        }
    }

    vector<ll> dp(1 << n, 0);
    dp[0] = 1;
    auto contain = [](int i, int j) -> bool {
        return ((i >> j) & 1);
    };
    for(int i = 0; i < 1 << n; ++i){
        for(int j = 0; j < n; ++j){
            if (!contain(i, j) && !contain(dp1[i] | dp2[i], j)) {
                dp[i | (1 << j)] = (dp[i | (1 << j)] + dp[i]) % MOD;
            }
        }
    }
    cout << dp[(1 << n) - 1] << endl;
}
accuracy: 1
time_ms: 1350
memory_kb: 265444
final_rank: 9

code_snippet: #include<iostream>
#include<string>
#include<utility>
#include<algorithm>
#include<vector>
#include<queue>
#include<cmath>
#include <random>
using namespace std;
using ll= long long;
#define rep(i,n) for(ll i=0; i<ll(n); i++)
#define repr(i,n) for(ll i=(n)-1; i>=0; i--)
template<class T> void chmin(T& l, T r){ if(r < l) l = r; }
template<class T> void chmax(T& l, T r){ if(l < r) l = r; }

const int MOD = 998244353;

void testcase(){
    ll n,m; cin >> n >> m;
    int M = (1 << n) - 1;
    vector<int> loh(1<<n,M), hih(1<<n,M);
    rep(i,n) hih[1<<i] -= 1 << i;
    rep(i,m){
        int a,b,c; cin >> a >> b >> c; a--; b--; c--;
        int m = (1 << a) | (1 << c);
        hih[m] &= (M - (1<<b));
        loh[M-m] &= (M - (1<<b));
    }
    rep(d,n) rep(i,1<<n) if(!(i&(1<<d))) loh[i] &= loh[i|(1<<d)];
    rep(d,n) rep(i,1<<n) if(!(i&(1<<d))) hih[i|(1<<d)] &= hih[i];
    rep(i,1<<n) loh[i] &= hih[i];
    vector<int> dp(1<<n);
    dp[0] = 1;
    rep(i,1<<n){
        int q = loh[i];
        rep(b,n) if(q&(1<<b)){
            dp[i|(1<<b)] += dp[i];
            if(dp[i|(1<<b)] >= MOD) dp[i|(1<<b)] -= MOD;
        }
    }
    cout << dp[M] << "\n";
}

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    testcase();
    return 0;
}
accuracy: 1
time_ms: 1400
memory_kb: 199732
final_rank: 6

code_snippet: #include<iostream>
#include<string>
#include<utility>
#include<algorithm>
#include<vector>
#include<queue>
#include<cmath>
#include <random>
using namespace std;
using ll= long long;
#define rep(i,n) for(ll i=0; i<ll(n); i++)
#define repr(i,n) for(ll i=(n)-1; i>=0; i--)
template<class T> void chmin(T& l, T r){ if(r < l) l = r; }
template<class T> void chmax(T& l, T r){ if(l < r) l = r; }

const int MOD = 998244353;

void testcase(){
    ll n,m; cin >> n >> m;
    int M = (1 << n) - 1;
    vector<int> loh(1<<n,M), hih(1<<n,M);
    rep(i,n) hih[1<<i] -= 1 << i;
    rep(i,m){
        int a,b,c; cin >> a >> b >> c; a--; b--; c--;
        int m = (1 << a) | (1 << c);
        hih[m] &= (M - (1<<b));
        loh[M-m] &= (M - (1<<b));
    }
    rep(d,n) rep(i,1<<n) if(!(i&(1<<d))) loh[i] &= loh[i|(1<<d)];
    rep(d,n) rep(i,1<<n) if(!(i&(1<<d))) hih[i|(1<<d)] &= hih[i];
    rep(i,1<<n) loh[i] &= hih[i];
    vector<int> dp(1<<n);
    dp[0] = 1;
    rep(i,1<<n){
        int q = loh[i];
        rep(b,n) if(q&(1<<b)){
            dp[i|(1<<b)] += dp[i];
            if(dp[i|(1<<b)] >= MOD) dp[i|(1<<b)] -= MOD;
        }
    }
    cout << dp[M] << "\n";
}

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    testcase();
    return 0;
}
accuracy: 1
time_ms: 1390
memory_kb: 199732
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define all(v) (v).begin(),(v).end()
#define pb(a) push_back(a)
#define rep(i, n) for(int i=0;i<n;i++)
#define foa(e, v) for(auto&& e : v)
using ll = long long;
const ll MOD7 = 1000000007, MOD998 = 998244353, INF = (1LL << 60);
#define dout(a) cout<<fixed<<setprecision(10)<<a<<endl;

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    int n, m;
    cin >> n >> m;
    vector<int> ng(1 << n, 0), ng2(1 << n, 0);
    iota(all(ng), 0);
    rep(i, m) {
        int a, b, c;
        cin >> a >> b >> c;
        a --; b --; c --;
        ng[(1 << a) | (1 << c)] |= 1 << b;
        ng2[(~((1 << a) | (1 << c))) & ((1 << n) - 1)] |= 1 << b;
    }
    rep(bit, 1 << n) {
        rep(i, n) {
            if(bit >> i & 1) continue;
            ng[bit | (1 << i)] |= ng[bit];
        }
    }
    for(int bit = (1 << n) - 1; bit >= 0; bit --) {
        rep(i, n) {
            if(bit >> i & 1) {
                ng2[bit ^ (1 << i)] |= ng2[bit];
            }
        }
    }
    ll mod = MOD998;
    vector<ll> dp(1 << n, 0LL);
    dp[0] = 1;
    rep(bit, 1 << n) {
        if(bit & ng2[bit]) continue;
        rep(i, n) {
            if(ng[bit] >> i & 1) continue;
            dp[bit | (1 << i)] += dp[bit];
            if(dp[bit | (1 << i)] >= mod) dp[bit | (1 << i)] -= mod;
        }
    }
    cout << dp.back() << endl;
    return 0;
}
accuracy: 1
time_ms: 2250
memory_kb: 265172
final_rank: 20

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pi;
typedef vector<ll> vi;
typedef vector<vi> vvi;
#define FOR(i,l,r) for(ll i=l;i<r;i++)
#define REP(i,n) FOR(i,0,n)
#define sz(A) (ll)(A.size())
struct dsu{
    vi nec;
    dsu(ll N):nec(N,-1){}
    ll leader(ll v){
        while(nec[v]>=0)v=nec[v];
        return v;
    }
    bool same(ll u,ll v){return leader(u)==leader(v);}
    ll size(ll v){return -nec[leader(v)];}
    ll merge(ll u,ll v){
        u=leader(u);
        v=leader(v);
        if(u==v)return u;
        if(nec[u]<nec[v])swap(u,v);
        nec[v]+=nec[u];
        nec[u]=v;
        return v;
    }
    vvi groups(){
        vvi gr(sz(nec));
        REP(i,sz(nec))gr[leader(i)].emplace_back(i);
        vvi res;
        REP(i,sz(nec))if(gr[i].size())res.emplace_back(gr[i]);
        return res;
    }
};
int main(){
    ll N,M;cin>>N>>M;
    vi A(M),B(M),C(M);
    REP(i,M)cin>>A[i]>>B[i]>>C[i];
    vector<vector<pi>>Q(N);
    REP(i,M){
        A[i]--;B[i]--;C[i]--;
        Q[A[i]].emplace_back(pi(C[i],B[i]));
        Q[C[i]].emplace_back(pi(A[i],B[i]));
    }
    vector<bitset<16777216>>pos(N);
    REP(i,N){
        dsu D(N);
        for(auto[l,r]:Q[i])D.merge(l,r);
        auto G=D.groups();
        vi gr;
        REP(i,sz(G)){
            ll s=0;
            for(auto v:G[i])s+=1<<v;
            gr.emplace_back(s);
        }
        pos[i][0]=1;
        REP(j,sz(gr))pos[i]=pos[i]|(pos[i]<<gr[j]);
    }
    const ll mod=998244353;
    vi DP(1<<N);
    DP[0]=1;
    REP(i,1<<N)REP(j,N)if((i>>j)%2==0&&pos[j][i]){
        DP[i+(1<<j)]+=DP[i];
        DP[i+(1<<j)]%=mod;
    }
    cout<<DP.back()<<endl;
    return 0;
}
accuracy: 1
time_ms: 1360
memory_kb: 190044
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep2(i, n) for (ll i = 0; i < (n); i++)
#define rep3(i, a, b) for (ll i = a; i < (b); i++)
#define overload(a, b, c, d, ...) d
#define rep(...) overload(__VA_ARGS__, rep3, rep2)(__VA_ARGS__)
#define all(a) begin(a), end(a)
#define sz(a) ssize(a)
bool chmin(auto& a, auto b) {
    return a > b ? a = b, 1 : 0;
}
bool chmax(auto& a, auto b) {
    return a < b ? a = b, 1 : 0;
}

int main() {
    cin.tie(0)->sync_with_stdio(0);
    int n, m;
    cin >> n >> m;
    vector<tuple<int, int, int>> a(m);
    for (auto& [x, y, z]: a) cin >> x >> y >> z, x--, y--, z--;

    const int N = 1 << n;
    vector<int> U(N);
    vector<int> D(N);

    for (auto [x, y, z]: a) {
        U[(1 << x) | (1 << z)] |= 1 << y;
        D[(N - 1) ^ ((1 << x) | (1 << z))] |= 1 << y;
    }

    rep(i, n) rep(s, N) {
        U[s | (1 << i)] |= U[s];
    }

    rep(i, n) {
        for (int s = N; s-- > 0; ) {
            D[s & ((N - 1) ^ (1 << i))] |= D[s];
        }
    }

    constexpr ll mod = 998244353;
    vector<ll> dp(N);
    dp[0] = 1;
    rep(s, N) {
        rep(i, n) {
            if (s & (1 << i)) continue;
            if (D[s] & (1 << i)) continue;
            if (U[s] & (1 << i)) continue;
            dp[s | (1 << i)] += dp[s];
            if (dp[s | (1 << i)] >= mod) dp[s | (1 << i)] -= mod;
        }
    }
    cout << dp.back() << '\n';
}
accuracy: 1
time_ms: 1480
memory_kb: 265536
final_rank: 12

code_snippet: #include "bits/stdc++.h"

    using namespace std;

    #define REP(i, n) for(int i = 0;i < n;i++)
    #define REPR(i, n) for(int i = n;i >= 0;i--)
    #define FOR(i, m, n) for(ll i = m;i < n;i++)
    #define FORR(i, m, n) for(ll i = m;i >= n;i--)
    #define REPO(i, n) for(ll i = 1;i <= n;i++)
    #define ll long long
    #define INF (ll)1ll << 60
    #define MINF (-1 * INF)
    #define ALL(n) n.begin(),n.end()
    #define MOD (ll)1000000007
    #define P pair<ll, ll>


    ll n, m, a[100000], b[100000], c[100000];
    vector<ll> v(16800000), dp(16800000);
    int main() {
        cin >> n >> m;
        REP(i, m){
            cin >> a[i] >> b[i] >> c[i];
            a[i]--;
            b[i]--;
            c[i]--;
            v[(1ll << a[i]) | (1ll << c[i])] |= (1ll << b[i]);
        }
        REP(i, n){
            ll bit = 1ll << i;
            REP(j, 1ll << n){
                if(j & bit) v[j] |= v[j ^ bit];
            }
        }
        dp[0] = 1;
        REP(i, 1ll << n){
            REP(j, n){
                if((i & (1ll << j)))continue;
                if((v[i] & (1ll << j)) or (v[(1ll << n) - 1 - i] & (1ll << j))) continue;
                dp[i | (1ll << j)] += dp[i];
                dp[i | (1ll << j)] %= 998244353;
            }
        }
        cout << dp[(1ll << n) - 1] << endl;
    }
accuracy: 1
time_ms: 1600
memory_kb: 265548
final_rank: 14