#include <bits/stdc++.h>
using namespace std;
vector<pair<long long, int>> pf(long long n) {
  vector<pair<long long, int>> ans;
  for (long long i = 2; i * i <= n; ++i) {
    if (n % i == 0) {
      int cnt = 0;
      while (n % i == 0) n /= i, ++cnt;
      ans.emplace_back(i, cnt);
    }
  }
  if (n > 1) ans.emplace_back(n, 1);
  sort(ans.rbegin(), ans.rend());
  return ans;
}
void _factors(const vector<pair<long long, int>>& pfs, int i, int N,
              long long cur, vector<long long>& ans) {
  if (i == N) return void(ans.push_back(cur));
  for (int c = 0; c <= pfs[i].second; cur *= pfs[i].first, ++c) {
    _factors(pfs, i + 1, N, cur, ans);
  }
}
vector<long long> factors(long long n) {
  vector<long long> ans;
  auto pfs = pf(n);
  _factors(pfs, 0, (int)pfs.size(), 1, ans);
  return ans;
}
vector<long long> row_types;
vector<long long> col_types;
struct block_type_t {
  long long rows;
  long long cols;
  long long count;
  bool operator<(const block_type_t& other) const {
    if (rows < other.rows) return true;
    if (rows > other.rows) return false;
    if (cols < other.cols) return true;
    if (cols > other.cols) return false;
    assert(count == other.count);
    return false;
  }
  long long vblocks;
  long long hblocks;
};
block_type_t B[200005];
vector<vector<long long>> grid;
long long gcd(long long a, long long b) { return b ? gcd(b, a % b) : a; }
int main() {
  int N;
  scanf("%d", &N);
  for (int i = 0; i < (N); ++i) {
    scanf(
        "%I64d"
        "%I64d"
        "%I64d",
        &B[i].rows, &B[i].cols, &B[i].count);
    row_types.push_back(B[i].rows);
    col_types.push_back(B[i].cols);
  }
  sort(B, B + N);
  sort(row_types.begin(), row_types.end());
  row_types.resize(unique(row_types.begin(), row_types.end()) -
                   row_types.begin());
  sort(col_types.begin(), col_types.end());
  col_types.resize(unique(col_types.begin(), col_types.end()) -
                   col_types.begin());
  int R = row_types.size(), C = col_types.size();
  if (R * C != N) {
    printf(
        "%I64d"
        "\n",
        0ll);
    return 0;
  }
  grid.resize(R, vector<long long>(C));
  int k = 0;
  for (int i = 0; i < (R); ++i) {
    for (int j = 0; j < (C); ++j) {
      grid[i][j] = B[k++].count;
    }
  }
  vector<long long> rows(R);
  vector<long long> cols(C);
  vector<long long> row_gcd(R, 0);
  vector<long long> col_gcd(C, 0);
  long long ways = 0;
  for (int i = 0; i < (R); ++i)
    for (int j = 0; j < (C); ++j) row_gcd[i] = gcd(row_gcd[i], grid[i][j]);
  for (int j = 0; j < (C); ++j)
    for (int i = 0; i < (R); ++i) col_gcd[j] = gcd(col_gcd[j], grid[i][j]);
  auto F = factors(row_gcd[0]);
  assert(F.size() <= 6000);
  assert((F.size() * (R + C)) <= 300000000);
  for (int i = 0; i < (R); ++i) assert(row_gcd[i] > 0);
  for (int j = 0; j < (C); ++j) assert(col_gcd[j] > 0);
  for (const auto& f : F) {
    bool works = true;
    rows[0] = f;
    cols[0] = grid[0][0] / f;
    assert(rows[0] * cols[0] == grid[0][0]);
    assert(rows[0] > 0);
    assert(cols[0] > 0);
    for (int i = 0; i < (R); ++i) rows[i] = grid[i][0] / cols[0];
    for (int j = 0; j < (C); ++j) cols[j] = grid[0][j] / rows[0];
    assert(rows[0] == f);
    assert(cols[0] * f == grid[0][0]);
    for (int i = 0; i < (R); ++i)
      if (rows[i] == 0) works = false;
    for (int j = 0; j < (C); ++j)
      if (cols[j] == 0) works = false;
    if (!works) continue;
    for (int i = 0; i < (R); ++i) assert(rows[i] > 0);
    for (int j = 0; j < (C); ++j) assert(cols[j] > 0);
    for (int i = 0; i < (R); ++i)
      if (row_gcd[i] % rows[i]) works = false;
    for (int j = 0; j < (C); ++j)
      if (col_gcd[j] % cols[j]) works = false;
    if (works) ++ways;
  }
  printf(
      "%I64d"
      "\n",
      ways);
  return 0;
}
