#include <bits/stdc++.h>
using namespace std;
long long fpm(long long b, long long e, long long m) {
  long long t = 1;
  for (; e; e >>= 1, b = b * b % m) e & 1 ? t = t * b % m : 0;
  return t;
}
template <class T>
inline bool chkmin(T &a, T b) {
  return a > b ? a = b, true : false;
}
template <class T>
inline bool chkmax(T &a, T b) {
  return a < b ? a = b, true : false;
}
template <class T>
inline T sqr(T x) {
  return x * x;
}
template <class edge>
struct Graph {
  vector<vector<edge> > adj;
  Graph(int n) {
    adj.clear();
    adj.resize(n + 5);
  }
  void adde(int s, edge e) { adj[s].push_back(e); }
  typename vector<edge>::iterator operator[](int t) { return adj[t].begin(); }
};
const int maxn = 1100;
typedef int arr32[maxn];
arr32 col, row, vrow, vcol;
int noans, mod;
int main() {
  ios_base::sync_with_stdio(false);
  int n, m, K;
  cin >> n >> m >> K;
  for (int i = 1; i <= n; ++i) row[i] = m, vrow[i] = 1;
  for (int j = 1; j <= m; ++j) col[j] = n, vcol[j] = 1;
  for (int i = 1, a, b, c; i <= K; ++i)
    cin >> a >> b >> c, --row[a], --col[b], vrow[a] *= c, vcol[b] *= c;
  int unx = 0;
  if (K < n) {
    for (int i = 1; i <= n; ++i)
      if (row[i])
        unx += row[i] - 1;
      else if (vrow[i] != -1)
        noans = 1;
    unx -= m - 1;
  } else {
    for (int j = 1; j <= m; ++j)
      if (col[j])
        unx += col[j] - 1;
      else if (vcol[j] != -1)
        noans = 1;
    unx -= n - 1;
  }
  cin >> mod;
  if (noans || (n & 1) != (m & 1))
    cout << 0 << endl;
  else
    cout << fpm(2, unx, mod) << endl;
  return 0;
}
