#include <bits/stdc++.h>
using namespace std;
mt19937 rng(static_cast<unsigned int>(
    chrono::steady_clock::now().time_since_epoch().count()));
template <typename num_t>
inline void add_mod(num_t& a, const long long& b, const int& m) {
  a = (a + b) % m;
  if (a >= m) a -= m;
  if (a < 0) a += m;
}
template <typename num_t>
inline bool update_max(num_t& a, const num_t& b) {
  return a < b ? a = b, true : false;
}
template <typename num_t>
inline bool update_min(num_t& a, const num_t& b) {
  return a > b ? a = b, true : false;
}
template <typename num_t>
num_t gcd(num_t lhs, num_t rhs) {
  return !lhs ? rhs : gcd(rhs % lhs, lhs);
}
template <typename num_t>
num_t pw(num_t n, num_t k, const num_t& mod) {
  if (k == -1) k = mod - 2;
  num_t res = 1;
  for (; k > 0; k >>= 1) {
    if (k & 1) res = 1ll * res * n % mod;
    n = 1ll * n * n % mod;
  }
  return res % mod;
}
const int inf = 1e9 + 7;
const int mod = 998244353;
const long long ll_inf = (long long)inf * inf + 7;
const int maxn = 4000 + 7;
struct InverseModule {
  static const int MOD = ::mod;
  static const int MAX_N = 1e6 + 7;
  int fact[MAX_N];
  int inv_fact[MAX_N];
  InverseModule() {
    fact[0] = 1;
    for (int i = 1; i < MAX_N; ++i) {
      fact[i] = (long long)fact[i - 1] * i % MOD;
    }
    inv_fact[MAX_N - 1] = inverse(fact[MAX_N - 1]);
    for (int i = MAX_N - 2; i >= 0; --i) {
      inv_fact[i] = (long long)inv_fact[i + 1] * (i + 1) % MOD;
    }
  }
  int inverse(int x, int mod = MOD) {
    int r = mod, newr = x;
    int t = 0, newt = 1;
    while (newr > 0) {
      int q = r / newr;
      int tmp = newr;
      newr = r % newr;
      r = tmp;
      tmp = newt;
      newt = t - q * newt;
      t = tmp;
    }
    if (t < 0) t += mod;
    return t;
  }
  int choose(int n, int k) {
    return (long long)fact[n] * inv_fact[n - k] % MOD * inv_fact[k] % MOD;
  }
  int perm(int n, int k) { return (long long)fact[n] * inv_fact[n - k] % MOD; }
  long long pw(long long x, long long k, const long long& mod = MOD) {
    long long res = 1 % mod;
    for (; k > 0; k >>= 1) {
      if (k & 1) res = res * x % mod;
      x = x * x % mod;
    }
    return res;
  }
  pair<int, int> extended_euclid(int a, int b) {
    int s0 = 1, t0 = 0;
    int s1 = 0, t1 = 1;
    while (b > 0) {
      int q = a / b;
      int tmp = 0;
      tmp = s1;
      s1 = s0 - q * s1;
      s0 = tmp;
      tmp = t1;
      t1 = t0 - q * t1;
      t0 = tmp;
      tmp = b;
      b = a - q * b;
      a = tmp;
    }
    return {s0, t0};
  }
  int stirling_second_kind(int n, int k) {
    long long res = 0;
    for (int j = 0; j <= k; ++j) {
      long long temp = 1ll * choose(k, j) * pw(j, n);
      if ((k - j) & 1)
        res = (res - temp + MOD) % MOD;
      else
        res = (res + temp) % MOD;
    }
    return res * inv_fact[k] % MOD;
  }
} inv;
int n, m, k;
long long dp[2][maxn];
long long f[maxn][maxn];
void pre_calc() {
  f[0][0] = 1;
  for (int len = 1; len < maxn; ++len) {
    for (int num_brick = (0), _b = (maxn); num_brick < _b; ++num_brick) {
      f[len][num_brick] = f[len - 1][num_brick];
      if (len >= 2 && num_brick > 0)
        add_mod(f[len][num_brick], f[len - 2][num_brick - 1], mod);
    }
  }
}
vector<long long> calc(vector<bool> arr) {
  int cur = 0;
  for (int i = (0), _b = (maxn); i < _b; ++i) dp[cur][i] = 0;
  dp[cur][0] = 1;
  for (int i = 0; i < arr.size(); ++i)
    if (arr[i]) {
      int nxt_i = i;
      while (nxt_i < arr.size() && arr[nxt_i]) ++nxt_i;
      int len = nxt_i - i;
      i = nxt_i - 1;
      if (len < 2) continue;
      int pre = cur;
      cur ^= 1;
      for (int i = (0), _b = (maxn); i < _b; ++i) dp[cur][i] = dp[pre][i];
      for (int d = 1; d * 2 <= len; ++d) {
        for (int pre_d = 0; pre_d < maxn; ++pre_d)
          if (dp[pre][pre_d]) {
            add_mod(dp[cur][d + pre_d], dp[pre][pre_d] * f[len][d], mod);
          }
      }
    }
  return vector<long long>(dp[cur], dp[cur] + maxn);
}
void solve() {
  pre_calc();
  cin >> n >> m >> k;
  vector<bool> valid_row(n, true), valid_col(m, true);
  for (int i = (0), _b = (k); i < _b; ++i) {
    int u1, v1, u2, v2;
    cin >> u1 >> v1 >> u2 >> v2;
    valid_row[--u1] = false;
    valid_row[--u2] = false;
    valid_col[--v1] = false;
    valid_col[--v2] = false;
  }
  int total_row = 0;
  int total_col = 0;
  for (int i = (0), _b = (n); i < _b; ++i) total_row += valid_row[i];
  for (int j = (0), _b = (m); j < _b; ++j) total_col += valid_col[j];
  vector<long long> lhs = calc(valid_row), rhs = calc(valid_col);
  long long res = 0;
  for (int a = 0; a < maxn; ++a)
    if (lhs[a])
      for (int b = 0; b < maxn; ++b)
        if (rhs[b]) {
          if (2 * a + b > total_row || a + 2 * b > total_col) break;
          long long cur = lhs[a] * rhs[b] % mod;
          cur = cur * inv.choose(total_row - a * 2, b) % mod;
          cur = cur * inv.choose(total_col - b * 2, a) % mod;
          cur = cur * inv.fact[a] % mod * inv.fact[b] % mod;
          add_mod(res, cur, mod);
        }
  cout << res << '\n';
}
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  const bool multiple_test = false;
  int test = 1;
  if (multiple_test) cin >> test;
  for (int i = 0; i < test; ++i) {
    solve();
  }
}
