#include <bits/stdc++.h>
using namespace std;
const long long maxN = 309;
const long long INF = 1e9 + 7;
long long bin(long long a, long long b) {
  if (b == 0) {
    return 1;
  } else {
    long long res = bin(a, b / 2);
    res = res * res % INF;
    if (b % 2 == 1) {
      res = res * a % INF;
    }
    return res;
  }
}
long long fact[4 * maxN];
long long rev[4 * maxN];
map<long long, long long> mp;
long long equiv[maxN];
long long d[4 * maxN][maxN];
static bool was[4 * maxN][maxN];
long long get_c(long long a, long long b) {
  return (long long)fact[a] * rev[a - b] % INF * rev[b] % INF;
}
long long lazy(long long windows, long long i, long long num) {
  if (i == num - 1) {
    if (windows == equiv[i]) {
      return 1;
    } else {
      return 0;
    }
  }
  if (was[windows][i]) {
    return d[windows][i];
  }
  long long res = 0;
  for (long long k = 0; k <= min(windows - 1, equiv[i]); k++) {
    for (long long j = 0; j <= min(equiv[i] - k, (windows - k) * 2); j++) {
      res =
          (res +
           (long long)get_c(windows, k) * get_c((windows - k) * 2, j) % INF *
               get_c(equiv[i] - j - k + (windows - k) - 1, equiv[i] - j - k) %
               INF * lazy((windows - k) + equiv[i] - j - k, i + 1, num) % INF) %
          INF;
    }
  }
  d[windows][i] = res;
  was[windows][i] = true;
  return d[windows][i];
}
int main() {
  fact[0] = 1;
  for (long long i = 1; i < 4 * maxN; i++) {
    fact[i] = (long long)fact[i - 1] * i % INF;
  }
  for (long long i = 0; i < 4 * maxN; i++) {
    rev[i] = bin(fact[i], INF - 2);
  }
  long long n;
  cin >> n;
  for (long long i = 0; i < n; i++) {
    long long a;
    cin >> a;
    bool truth = false;
    long long need;
    for (auto b : mp) {
      long long key = b.first;
      long long res = key * a;
      long long l = 1, r = INF;
      while (l + 1 != r) {
        long long m = (l + r) / 2;
        if (res < m * m) {
          r = m;
        } else {
          l = m;
        }
      }
      if (l * l == res) {
        need = key;
        truth = true;
        break;
      }
    }
    if (!truth) {
      mp[a] = 1;
    } else {
      mp[need]++;
    }
  }
  long long nxt = 0;
  for (auto b : mp) {
    equiv[nxt++] = b.second;
  }
  long long res = lazy(1, 0, nxt);
  for (long long i = 0; i < nxt; i++) {
    res = res * fact[equiv[i]] % INF;
  }
  cout << res << endl;
  return 0;
}
