#include <bits/stdc++.h>
#pragma gcc optimize("Ofast")
#pragma gcc optimize("O3")
#pragma gcc target("avx,avx2,ffa,sse,sse2,sse3,sse3.1,sse4,sse4.2,sse5")
using namespace std;
using ll = long long;
using ull = unsigned long long;
using pii = pair<int, int>;
using pil = pair<int, ll>;
using pli = pair<ll, int>;
using pll = pair<ll, ll>;
using ld = long double;
template <typename T1, typename T2>
bool chkmin(T1& x, T2 y) {
  return y < x ? (x = y, true) : false;
}
template <typename T1, typename T2>
bool chkmax(T1& x, T2 y) {
  return y > x ? (x = y, true) : false;
}
void debug_out() { cerr << endl; }
template <typename T1, typename... T2>
void debug_out(T1 A, T2... B) {
  cerr << ' ' << A;
  debug_out(B...);
}
template <typename T>
void mdebug_out(T* a, int n) {
  for (int i = 0; i < n; ++i) {
    cerr << a[i] << ' ';
  }
  cerr << endl;
}
template <typename T>
ostream& operator<<(ostream& stream, const vector<T>& v) {
  for (auto& x : v) {
    stream << x << ' ';
  }
  return stream;
}
template <typename T1, typename T2>
ostream& operator<<(ostream& stream, const pair<T1, T2>& p) {
  return stream << p.first << ' ' << p.second;
}
const int MOD = 998244353;
void vadd(int& a, int b) {
  if ((a += b) >= MOD) {
    a -= MOD;
  }
}
void vsub(int& a, int b) {
  if ((a -= b) < 0) {
    a += MOD;
  }
}
const int N = 18;
int n, m;
int G[N], revG[N];
int allG[N];
int cnt[1 << N];
int popcnt[1 << N];
bool good[1 << N];
void maskdebug(int mask) {
  for (int i = 0; i < n; ++i) {
    if ((mask >> i) & 1) {
      cerr << i << ' ';
    }
  }
  cerr << endl;
}
int32_t main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  cin >> n >> m;
  for (int j = 0; j < m; ++j) {
    int a, b;
    cin >> a >> b;
    --a;
    --b;
    G[a] |= 1 << b;
    revG[b] |= 1 << a;
  }
  for (int v = 0; v < n; ++v) {
    allG[v] = G[v] | revG[v];
  }
  for (int mask = 1; mask < (1 << n); ++mask) {
    popcnt[mask] = (mask & 1) + popcnt[mask >> 1];
  }
  for (int mask = 0; mask < (1 << n); ++mask) {
    good[mask] = true;
    for (int v = 0; v < n; ++v) {
      if (((mask >> v) & 1) && (allG[v] & mask)) {
        good[mask] = false;
        break;
      }
    }
  }
  cnt[0] = 1;
  for (int mask = 1; mask < (1 << n); ++mask) {
    if (popcnt[mask] == 1) {
      cnt[mask] = 1;
      continue;
    }
    for (int subm = mask; subm; subm = (subm - 1) & mask) {
      if (good[subm]) {
        int rem = mask ^ subm;
        if (popcnt[subm] & 1) {
          vadd(cnt[mask], cnt[rem]);
        } else {
          vsub(cnt[mask], cnt[rem]);
        }
      }
    }
  }
  cout << ((cnt[(1 << n) - 1] * (ll)m % MOD) * (ll)(MOD + 1) / 2) % MOD << '\n';
  return 0;
}
