#include <bits/stdc++.h>
using namespace std;
const int N = 2e4 + 10, MOD = 998244353, M = 1e8 + 2;
vector<int> primes, clr;
bool comp[N], sign[N];
int n, a[N], res[N];
bitset<M> pve, nve;
void sieve() {
  comp[0] = comp[1] = true;
  for (int i = 2; i * i <= N; i++) {
    if (!comp[i])
      for (int j = i * i; j < N; j += i) {
        comp[j] = true;
      }
  }
}
int main() {
  sieve();
  for (int i = 0; i < N; i++)
    if (!comp[i]) primes.push_back(i);
  scanf("%d", &n);
  for (int i = 0; i < n; i++) {
    scanf("%d", a + i);
    bool pve = (a[i] >= 0);
    if (!pve) a[i] *= -1;
    sign[i] = pve;
    int ind = 0;
    int mul = 1;
    while (a[i] >= 1) {
      if (primes[ind] * primes[ind] > a[i])
        break;
      else {
        int cnt = 0;
        while (a[i] % primes[ind] == 0) {
          a[i] /= primes[ind];
          cnt++;
        }
        cnt %= 2;
        if (cnt) mul *= primes[ind];
      }
      ind++;
    }
    a[i] *= mul;
  }
  for (int i = 0; i < n; i++) {
    for (int i = 0; i < clr.size(); i++) {
      pve[clr[i]] = nve[clr[i]] = 0;
    }
    clr.clear();
    int gr = 0;
    bool hv = false;
    for (int j = i; j < n; j++) {
      if (a[j] == 0) {
        if (gr == 0) {
          gr++;
          hv = true;
        }
        res[gr]++;
        continue;
      }
      if (sign[j]) {
        if (!pve[a[j]] && !hv) {
          pve[a[j]] = 1;
          clr.push_back(a[j]);
          gr++;
        } else if (!pve[a[j]] && hv) {
          pve[a[j]] = 1;
          clr.push_back(a[j]);
          hv = false;
        }
      } else {
        if (!nve[a[j]] && !hv) {
          nve[a[j]] = 1;
          clr.push_back(a[j]);
          gr++;
        } else if (!nve[a[j]] && hv) {
          nve[a[j]] = 1;
          clr.push_back(a[j]);
          hv = false;
        }
      }
      res[gr]++;
    }
  }
  for (int i = 1; i <= n; i++) printf("%d ", res[i]);
  return 0;
}
