#include <bits/stdc++.h>
using namespace std;
using lint = long long int;
using pint = pair<int, int>;
using plint = pair<lint, lint>;
struct fast_ios {
  fast_ios() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(20);
  };
} fast_ios_;
template <typename T>
void ndarray(vector<T> &vec, int len) {
  vec.resize(len);
}
template <typename T, typename... Args>
void ndarray(vector<T> &vec, int len, Args... args) {
  vec.resize(len);
  for (auto &v : vec) ndarray(v, args...);
}
template <typename T>
bool mmax(T &m, const T q) {
  if (m < q) {
    m = q;
    return true;
  } else
    return false;
}
template <typename T>
bool mmin(T &m, const T q) {
  if (m > q) {
    m = q;
    return true;
  } else
    return false;
}
template <typename T1, typename T2>
pair<T1, T2> operator+(const pair<T1, T2> &l, const pair<T1, T2> &r) {
  return make_pair(l.first + r.first, l.second + r.second);
}
template <typename T1, typename T2>
pair<T1, T2> operator-(const pair<T1, T2> &l, const pair<T1, T2> &r) {
  return make_pair(l.first - r.first, l.second - r.second);
}
template <typename T>
istream &operator>>(istream &is, vector<T> &vec) {
  for (auto &v : vec) is >> v;
  return is;
}
template <typename T>
ostream &operator<<(ostream &os, const vector<T> &vec) {
  os << "[";
  for (auto v : vec) os << v << ",";
  os << "]";
  return os;
}
template <typename T>
ostream &operator<<(ostream &os, const deque<T> &vec) {
  os << "deq[";
  for (auto v : vec) os << v << ",";
  os << "]";
  return os;
}
template <typename T>
ostream &operator<<(ostream &os, const set<T> &vec) {
  os << "{";
  for (auto v : vec) os << v << ",";
  os << "}";
  return os;
}
template <typename T>
ostream &operator<<(ostream &os, const unordered_set<T> &vec) {
  os << "{";
  for (auto v : vec) os << v << ",";
  os << "}";
  return os;
}
template <typename T>
ostream &operator<<(ostream &os, const multiset<T> &vec) {
  os << "{";
  for (auto v : vec) os << v << ",";
  os << "}";
  return os;
}
template <typename T>
ostream &operator<<(ostream &os, const unordered_multiset<T> &vec) {
  os << "{";
  for (auto v : vec) os << v << ",";
  os << "}";
  return os;
}
template <typename T1, typename T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &pa) {
  os << "(" << pa.first << "," << pa.second << ")";
  return os;
}
template <typename TK, typename TV>
ostream &operator<<(ostream &os, const map<TK, TV> &mp) {
  os << "{";
  for (auto v : mp) os << v.first << "=>" << v.second << ",";
  os << "}";
  return os;
}
template <typename TK, typename TV>
ostream &operator<<(ostream &os, const unordered_map<TK, TV> &mp) {
  os << "{";
  for (auto v : mp) os << v.first << "=>" << v.second << ",";
  os << "}";
  return os;
}
int H, W, N;
constexpr int Mmax = 2401;
constexpr lint MOD = 998244353;
vector<lint> fac, facInv, inv;
void facInit(int nmax) {
  fac = facInv = inv = vector<lint>(nmax + 1, 1);
  for (int i = 2; i <= nmax; i++) {
    fac[i] = fac[i - 1] * i % MOD;
    inv[i] = MOD - inv[MOD % i] * (MOD / i) % MOD;
    facInv[i] = facInv[i - 1] * inv[i] % MOD;
  }
}
lint nCr(lint n, lint r) {
  if (n < r || r < 0) return 0;
  if (n >= (int)fac.size()) facInit(n);
  return (fac[n] * facInv[r] % MOD) * facInv[n - r] % MOD;
}
vector<vector<int>> solve(set<int> X) {
  vector<vector<int>> ret(Mmax + 1, vector<int>(Mmax + 1));
  vector<vector<int>> dp_two(3601, vector<int>(Mmax + 1));
  dp_two[0][0] = 1;
  for (int x = (1), x_end_ = (3601); x < x_end_; x++) {
    dp_two[x] = dp_two[x - 1];
    if (X.count(x) and X.count(x - 1)) {
      for (int m = (1), m_end_ = (Mmax + 1); m < m_end_; m++)
        (dp_two[x][m] += dp_two[x - 2][m - 1]) %= MOD;
    }
  }
  for (int two = (0), two_end_ = (Mmax + 1); two < two_end_; two++) {
    int nokori = X.size() - two * 2;
    for (int one = (0), one_end_ = (min(Mmax, nokori) + 1); one < one_end_;
         one++) {
      ret[one][two] = (lint)dp_two.back()[two] * nCr(nokori, one) % MOD;
    }
  }
  return ret;
}
int main() {
  facInit(100000);
  cin >> H >> W >> N;
  set<int> X, Y;
  for (int i = (0), i_end_ = (H); i < i_end_; i++) X.insert(i + 1);
  for (int i = (0), i_end_ = (W); i < i_end_; i++) Y.insert(i + 1);
  for (int _ = (0), __end_ = (N * 2); _ < __end_; _++) {
    int x, y;
    cin >> x >> y;
    X.erase(x);
    Y.erase(y);
  }
  vector<vector<int>> M1 = solve(X);
  vector<vector<int>> M2 = solve(Y);
  lint ret = 0;
  for (int tate = (0), tate_end_ = (Mmax + 1); tate < tate_end_; tate++)
    for (int yoko = (0), yoko_end_ = (Mmax + 1); yoko < yoko_end_; yoko++) {
      (ret += (lint)M1[tate][yoko] * M2[yoko][tate] % MOD * fac[tate] % MOD *
              fac[yoko] % MOD) %= MOD;
    }
  cout << ret << endl;
}
