// by david942j
// {{{
#include <cstdio>
#include <cstring>
#include <set>
#include <map>
#include <ctime>
#include <vector>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <deque>
#include <cassert>
#include <queue>
#include <stack>
#include <cstdlib>
// #ifndef DAVID
// #include <bits/stdc++.h>
// #endif
#define openfile(s) freopen(s".in","r",stdin);freopen(s".out","w",stdout)
#define mpr std::make_pair
#define lg(x) (31-__builtin_clz(x))
#define lgll(x) (63-__builtin_clzll(x))
#define __count __builtin_popcount
#define __countll __builtin_popcountll
#define X first
#define Y second
#define mst(x) memset(x,0,sizeof(x))
#define mst1(x) memset(x,-1,sizeof(x))
#define ALL(c) (c).begin(),(c).end()
#define FOR(i,n) for(int i=0;i<n;i++)
#define FOR1(i,n) for(int i=1;i<=n;i++)
#define FORit(it,c) for(__typeof(c.begin()) it=c.begin();it!=c.end();++it)
#define pb push_back
#define RI(x) scanf("%d",&x)
#define RID(x) int x;RI(x)

#define IOS do {ios_base::sync_with_stdio(false); cin.tie(0); }while(0)
using namespace std;
template<typename T>
void _R( T &x ) { cin>>x; }
void _R( int &x ) { scanf("%d",&x); }
#ifdef PRId64
void _R( long long &x ) { scanf("%" PRId64,&x); }
#else
void _R( long long &x) {cin >> x;}
#endif
void _R( double &x ) { scanf("%lf",&x); }
void _R( char &x ) { scanf(" %c",&x); }
void _R( char *x ) { scanf("%s",x); }

void R() {}
template<typename T, typename... U>
void R( T& head, U&... tail ) {
  _R(head);
  R(tail...);
}

template<typename T>
void _W( const T &x ) { cout<<x; }
void _W( const int &x ) { printf("%d",x); }
template<typename T>
void _W( const vector<T> &x ) {
  for ( auto i=x.cbegin(); i!=x.cend(); i++ ) {
    if ( i!=x.cbegin() ) putchar(' ');
    _W(*i);
  }
}

void W() {}
template<typename T, typename... U>
void W( const T& head, const U&... tail ) {
  _W(head);
  putchar(sizeof...(tail)?' ':'\n');
  W(tail...);
}
#ifdef DAVID
#define debug(format, ...) fprintf(stderr, format, ##__VA_ARGS__)
#else
#define debug(...)
#endif
#define caset RID(T);FOR1(cas,T)
typedef long long LL;
typedef double LD;
typedef vector<int> VI;
typedef std::pair<int,int> PII;
template<class T>inline void maz(T &a,T b){if(a<b)a=b;}
template<class T>inline void miz(T &a,T b){if(a>b)a=b;}
template<class T>inline T abs(T a){return a>0?a:-a;}
// }}}

const int N = 1e5+10;
const int INF = 1e9+7;
const int MOD = 1e9+7;
int n;
int A[N];
VI pr;

set<int> S;
set<PII> E;

void prime() {
  static bool a[1000];
  for(int i=2;i<1000;i++) {
    if (!a[i]) {
      pr.pb(i);
      for (int j=i*i;j < 1000; j+=i)
        a[j]=1;
    }
  }
  // W(pr.size());
  // W(pr);
}

int ana(int v, int &a, int &b) {
  a = b = 0;
  for (auto p: pr)
    if (v % p == 0) {
      int k = 0;
      do {
        v /= p;
        k++;
      } while (v % p == 0);
      if (k & 1) {
        if (a == 0) a = p;
        else b = p;
      }
    }
    else if (v == 1) break;

  if (v != 1) {
    if (a == 0) a = v;
    else b = v;
  }
  if (a == 0) return 0;
  if (b == 0) return 1;
  return 2;
}

map<int, int> M;
int m[169][169];
VI G[200000];
void discrete() {
  FOR(i, pr.size())
    M[pr[i]] = i;

  int cur = pr.size();
  for(auto s: S)
    if (s > 1000 && M.count(s) == 0)
      M[s] = cur++;
  for(auto e: E) {
    assert(! (e.X > 1000 && M.count(e.X) == 0));
    if (e.Y > 1000 && M.count(e.Y) == 0)
      M[e.Y] = cur++;
  }
}

void ggraph() {
  for(auto e: E)
    if (e.Y > 1000) {
      G[M[e.Y]].pb(M[e.X]);
    }
}

void mgraph() {
  const int n = pr.size();

  FOR(i, n) {
    FOR(j, i)
      m[i][j] = m[j][i] = INF;
    m[i][i] = 0;
  }
  for(auto e: E) {
    const int &x = M[e.X], &y = M[e.Y];
    if (x < n && y < n)
      m[x][y] = m[y][x] = 1;
  }
}

void floyd() {
  mgraph();
  const int n = pr.size();

  FOR(k, n)
    FOR(i, n)
      FOR(j, n)
        if (m[i][k] != INF && m[k][j] != INF)
          miz(m[i][j], m[i][k] + m[k][j]);
}

int BFS(int x, int y) {
  queue<int> Q;
  const int n = pr.size();
  int dis[170];
  FOR(i, n)
    dis[i] = INF;
  Q.push(x); dis[x] = 0;
  while (!Q.empty()) {
    auto a = Q.front(); Q.pop();
    FOR(i, n)
      if (m[a][i] == 1 && dis[i] == INF) {
        dis[i] = dis[a] + 1;
        if (y == i)
          return dis[y];
        Q.push(i);
      }
  }

  return INF;
}

int small_cycle() {
  mgraph();
  const int n = pr.size();
  int ans = INF;
  FOR(i, n)
    FOR(j, i)
      if (m[j][i] == 1) {
        m[j][i] = m[i][j] = INF;
        int len = BFS(i, j);
        m[j][i] = m[i][j] = 1;
        miz(ans, len + 1);
      }
  return ans;
}

int small_endpoint() {
  VI v;
  for(auto s: S)
    if (s < 1000)
      v.pb(M[s]);
  int ans = INF;
  FOR(i, v.size())
    FOR(j, i)
      miz(ans, 2 + m[v[j]][v[i]]);
  return ans;
}

int big_cycle() {
  int ans = INF;
  FOR(x, M.size())
    FOR(i, G[x].size())
      FOR(j, i)
        miz(ans, m[G[x][i]][G[x][j]] + 2);
  return ans;
}

int big_small_endpoint() {
  static int best_end[170];
  const int n = pr.size();
  FOR(i, n)
    best_end[i] = INF;
  VI V;
  for(auto s: S)
    if (s < 1000)
      V.pb(M[s]);
  FOR(i, n)
    for(auto v: V)
      miz(best_end[i], 1 + m[i][v]);

  int ans = INF;
  for(auto s: S)
    if (s > 1000)
      for(auto y: G[M[s]])
        miz(ans, 2 + best_end[y]);

  return ans;
}

int big_big_endpoint() {
  int ans = INF;
  static bool has_bee[170];
  for(auto e: E)
    if (e.Y > 1000 && S.count(e.Y))
      has_bee[M[e.X]] = true;
  const int n = pr.size();
  FOR(i, n)
      if (has_bee[i])
        FOR(j, i)
          if (has_bee[j])
            miz(ans, m[i][j] + 4);
  return ans;
}

int solve() {
  int a, b;
  FOR(i, n) {
    if (A[i] == 1) return 1;

    int t = ana(A[i], a, b);
    // printf("~%d %d %d\n", t, a, b);
    if (t == 0) return 1;
    if (t == 1) {
      if (S.find(a) != S.end())
        return 2;
      else S.insert(a);
    }
    else {
      if (E.find(mpr(a, b)) != E.end())
        return 2;
      else E.insert(mpr(a,b));
    }
  }
  discrete();
  int ans = INF;
  miz(ans, small_cycle());
  floyd();
  miz(ans, small_endpoint());
  ggraph();
  miz(ans, big_small_endpoint());
  miz(ans, big_big_endpoint());
  miz(ans, big_cycle());

  if (ans == INF)
    return -1;
  return ans;
}

int main() {
  prime();
  R(n);
  FOR(i,n)
    R(A[i]);
  printf("%d\n", solve());
  return 0;
}

/*
3 2 2006 1003
4 2 2006 1003 17
3 2 2018 1009
3 2018 5045 10
5 1009 1013 3027 15 5065
 */


// by david942j
// {{{
#include <cstdio>
#include <cstring>
#include <set>
#include <map>
#include <ctime>
#include <vector>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <deque>
#include <cassert>
#include <queue>
#include <stack>
#include <cstdlib>
// #ifndef DAVID
// #include <bits/stdc++.h>
// #endif
#define openfile(s) freopen(s".in","r",stdin);freopen(s".out","w",stdout)
#define mpr std::make_pair
#define lg(x) (31-__builtin_clz(x))
#define lgll(x) (63-__builtin_clzll(x))
#define __count __builtin_popcount
#define __countll __builtin_popcountll
#define X first
#define Y second
#define mst(x) memset(x,0,sizeof(x))
#define mst1(x) memset(x,-1,sizeof(x))
#define ALL(c) (c).begin(),(c).end()
#define FOR(i,n) for(int i=0;i<n;i++)
#define FOR1(i,n) for(int i=1;i<=n;i++)
#define FORit(it,c) for(__typeof(c.begin()) it=c.begin();it!=c.end();++it)
#define pb push_back
#define RI(x) scanf("%d",&x)
#define RID(x) int x;RI(x)

#define IOS do {ios_base::sync_with_stdio(false); cin.tie(0); }while(0)
using namespace std;
template<typename T>
void _R( T &x ) { cin>>x; }
void _R( int &x ) { scanf("%d",&x); }
#ifdef PRId64
void _R( long long &x ) { scanf("%" PRId64,&x); }
#else
void _R( long long &x) {cin >> x;}
#endif
void _R( double &x ) { scanf("%lf",&x); }
void _R( char &x ) { scanf(" %c",&x); }
void _R( char *x ) { scanf("%s",x); }

void R() {}
template<typename T, typename... U>
void R( T& head, U&... tail ) {
  _R(head);
  R(tail...);
}

template<typename T>
void _W( const T &x ) { cout<<x; }
void _W( const int &x ) { printf("%d",x); }
template<typename T>
void _W( const vector<T> &x ) {
  for ( auto i=x.cbegin(); i!=x.cend(); i++ ) {
    if ( i!=x.cbegin() ) putchar(' ');
    _W(*i);
  }
}

void W() {}
template<typename T, typename... U>
void W( const T& head, const U&... tail ) {
  _W(head);
  putchar(sizeof...(tail)?' ':'\n');
  W(tail...);
}
#ifdef DAVID
#define debug(format, ...) fprintf(stderr, format, ##__VA_ARGS__)
#else
#define debug(...)
#endif
#define caset RID(T);FOR1(cas,T)
typedef long long LL;
typedef double LD;
typedef vector<int> VI;
typedef std::pair<int,int> PII;
template<class T>inline void maz(T &a,T b){if(a<b)a=b;}
template<class T>inline void miz(T &a,T b){if(a>b)a=b;}
template<class T>inline T abs(T a){return a>0?a:-a;}
// }}}

const int N = 1e5+10;
const int INF = 1e9+7;
const int MOD = 1e9+7;
int n;
int A[N];
VI pr;

set<int> S;
set<PII> E;

void prime() {
  static bool a[1000];
  for(int i=2;i<1000;i++) {
    if (!a[i]) {
      pr.pb(i);
      for (int j=i*i;j < 1000; j+=i)
        a[j]=1;
    }
  }
}

int ana(int v, int &a, int &b) {
  a = b = 0;
  for (auto p: pr)
    if (v % p == 0) {
      int k = 0;
      do {
        v /= p;
        k++;
      } while (v % p == 0);
      if (k & 1) {
        if (a == 0) a = p;
        else { assert(b == 0); b = p; }
      }
    }
    else if (v == 1) break;

  if (v != 1) {
    if (a == 0) a = v;
    else { assert(b == 0); b = v; }
  }
  if (a == 0) return 0;
  if (b == 0) return 1;
  return 2;
}

map<int, int> M;
int m[169][169];
VI G[100000];
void discrete() {
  FOR(i, pr.size())
    M[pr[i]] = i;

  int cur = pr.size();
  for(auto s: S)
    if (s > 1000 && M.count(s) == 0)
      M[s] = cur++;
  for(auto e: E) {
    assert(!(e.X > 1000));
    if (e.Y > 1000 && M.count(e.Y) == 0)
      M[e.Y] = cur++;
  }
  assert(cur < 100000);
  assert(cur == M.size());
}

void ggraph() {
  for(auto e: E)
    if (e.Y > 1000) {
      G[M[e.Y]].pb(M[e.X]);
    }
}

int Ans = INF;
void mgraph() {
  const int n = pr.size();

  FOR(i, n) {
    FOR(j, i)
      m[i][j] = m[j][i] = INF;
    m[i][i] = 0;
  }
  for(auto e: E) {
    const int &x = M[e.X], &y = M[e.Y];
    if (x < n && y < n)
      m[x][y] = m[y][x] = 1;
  }
  FOR(x, M.size())
    FOR(i, G[x].size())
      FOR(j, i) {
        miz(Ans, 2 + m[G[x][i]][G[x][j]]);
        miz(m[G[x][i]][G[x][j]], 2);
        miz(m[G[x][j]][G[x][i]], 2);
      }
}

int minimum_cycle() {
  const int n = pr.size();
  int ans = INF;
  int d[169][169];
  memcpy(d, m, sizeof(m));
  FOR(k, n) {
    FOR(i, k)
      if (d[k][i] != INF)
        FOR(j, i)
          miz(ans, d[k][i] + m[i][j] + d[j][k]);
    FOR(i, n)
      if (m[i][k] != INF)
        FOR(j, n)
          if (m[k][j] != INF)
            miz(m[i][j], m[i][k] + m[k][j]);
  }
  return ans;
}

int best[170], snd[170];
void update_end(int x, int v) {
  if (best[x] >= v) {
    snd[x] = best[x]; best[x] = v;
  } else if (snd[x] > v)
    snd[x] = v;
}

void good_end() {
  const int n = pr.size();
  FOR(i, n)
    best[i] = snd[i] = INF;
  VI V;
  for(auto s: S)
    if (s < 1000)
      V.pb(M[s]);
  FOR(i, n)
    for(auto v: V)
      update_end(i, 1 + m[i][v]);
  for(auto e: E)
    if (e.Y > 1000 && S.count(e.Y))
      update_end(M[e.X], 2);
}

int endpoint() {
  const int n = pr.size();
  int ans = INF;
  FOR(i, n)
    miz(ans, best[i] + snd[i]);
  FOR(i, n)
    FOR(j, n)
      if (m[i][j] != INF && i != j)
        miz(ans, best[i] + best[j] + m[i][j]);
  return ans;
}

int solve() {
  int a, b;
  FOR(i, n) {
    if (A[i] == 1) return 1;

    int t = ana(A[i], a, b);
    // printf("~%d %d %d\n", t, a, b);
    if (t == 0) return 1;
    if (t == 1) {
      if (S.find(a) != S.end())
        return 2;
      else S.insert(a);
    }
    else {
      assert(a < b && a && b);
      if (E.find(mpr(a, b)) != E.end())
        return 2;
      else E.insert(mpr(a,b));
    }
  }
  discrete();
  ggraph();
  mgraph();
  int ans = Ans;
  miz(ans, minimum_cycle());
  good_end();
  miz(ans, endpoint());

  if (ans == INF)
    return -1;
  return ans;
}

int main() {
  prime();
  R(n);
  FOR(i,n)
    R(A[i]);
  printf("%d\n", solve());
  return 0;
}

/*
4 2 2006 1003 17
3 2 2018 1009
3 2018 5045 10
5 1009 1013 3027 15 5065
5 2 2018 3027 3039 1013
3 6 2018 3027
4 2018 3027 3039 2026
4 1009 2018 3 3027 # 3
5 2018 1009 3039 1013 6
4 2018 2026 1009 1013
2 1009 2018
 */


// by david942j
// {{{
#include <cstdio>
#include <cstring>
#include <set>
#include <map>
#include <ctime>
#include <vector>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <deque>
#include <cassert>
#include <queue>
#include <stack>
#include <cstdlib>
// #ifndef DAVID
// #include <bits/stdc++.h>
// #endif
#define openfile(s) freopen(s".in","r",stdin);freopen(s".out","w",stdout)
#define mpr std::make_pair
#define lg(x) (31-__builtin_clz(x))
#define lgll(x) (63-__builtin_clzll(x))
#define __count __builtin_popcount
#define __countll __builtin_popcountll
#define X first
#define Y second
#define mst(x) memset(x,0,sizeof(x))
#define mst1(x) memset(x,-1,sizeof(x))
#define ALL(c) (c).begin(),(c).end()
#define FOR(i,n) for(int i=0;i<n;i++)
#define FOR1(i,n) for(int i=1;i<=n;i++)
#define FORit(it,c) for(__typeof(c.begin()) it=c.begin();it!=c.end();++it)
#define pb push_back
#define RI(x) scanf("%d",&x)
#define RID(x) int x;RI(x)

#define IOS do {ios_base::sync_with_stdio(false); cin.tie(0); }while(0)
using namespace std;
template<typename T>
void _R( T &x ) { cin>>x; }
void _R( int &x ) { scanf("%d",&x); }
#ifdef PRId64
void _R( long long &x ) { scanf("%" PRId64,&x); }
#else
void _R( long long &x) {cin >> x;}
#endif
void _R( double &x ) { scanf("%lf",&x); }
void _R( char &x ) { scanf(" %c",&x); }
void _R( char *x ) { scanf("%s",x); }

void R() {}
template<typename T, typename... U>
void R( T& head, U&... tail ) {
  _R(head);
  R(tail...);
}

template<typename T>
void _W( const T &x ) { cout<<x; }
void _W( const int &x ) { printf("%d",x); }
template<typename T>
void _W( const vector<T> &x ) {
  for ( auto i=x.cbegin(); i!=x.cend(); i++ ) {
    if ( i!=x.cbegin() ) putchar(' ');
    _W(*i);
  }
}

void W() {}
template<typename T, typename... U>
void W( const T& head, const U&... tail ) {
  _W(head);
  putchar(sizeof...(tail)?' ':'\n');
  W(tail...);
}
#ifdef DAVID
#define debug(format, ...) fprintf(stderr, format, ##__VA_ARGS__)
#else
#define debug(...)
#endif
#define caset RID(T);FOR1(cas,T)
typedef long long LL;
typedef double LD;
typedef vector<int> VI;
typedef std::pair<int,int> PII;
template<class T>inline void maz(T &a,T b){if(a<b)a=b;}
template<class T>inline void miz(T &a,T b){if(a>b)a=b;}
template<class T>inline T abs(T a){return a>0?a:-a;}
// }}}

const int N = 1e5+10;
const int INF = 1e9+7;
const int MOD = 1e9+7;
int n;
int A[N];
VI pr;

set<int> S;
set<PII> E;

void prime() {
  static bool a[1000];
  for(int i=2;i<1000;i++) {
    if (!a[i]) {
      pr.pb(i);
      for (int j=i*i;j < 1000; j+=i)
        a[j]=1;
    }
  }
}

int ana(int v, int &a, int &b) {
  a = b = 0;
  for (auto p: pr)
    if (v % p == 0) {
      int k = 0;
      do {
        v /= p;
        k++;
      } while (v % p == 0);
      if (k & 1) {
        if (a == 0) a = p;
        else { assert(b == 0); b = p; }
      }
    }
    else if (v == 1) break;

  if (v != 1) {
    if (a == 0) a = v;
    else { assert(b == 0); b = v; }
  }
  if (a == 0) return 0;
  if (b == 0) return 1;
  return 2;
}

map<int, int> M;
int m[169][169];
VI G[100000];
void discrete() {
  FOR(i, pr.size())
    M[pr[i]] = i;

  int cur = pr.size();
  for(auto s: S)
    if (s > 1000 && M.count(s) == 0)
      M[s] = cur++;
  for(auto e: E) {
    assert(!(e.X > 1000));
    if (e.Y > 1000 && M.count(e.Y) == 0)
      M[e.Y] = cur++;
  }
  assert(cur < 100000);
  assert(cur == M.size());
}

void ggraph() {
  for(auto e: E)
    if (e.Y > 1000) {
      G[M[e.Y]].pb(M[e.X]);
    }
}

int Ans = INF;
int se[169][169];
void mgraph() {
  const int n = pr.size();

  FOR(i, n) {
    FOR(j, i)
      m[i][j] = m[j][i] = INF;
    m[i][i] = 0;
  }
  for(auto e: E) {
    const int &x = M[e.X], &y = M[e.Y];
    if (x < n && y < n)
      m[x][y] = m[y][x] = 1;
  }
  FOR(x, M.size())
    FOR(i, G[x].size())
      FOR(j, i) {
        int &v = m[G[x][i]][G[x][j]];
        miz(Ans, 2 + v);
        if (v == INF)
          se[G[x][i]][G[x][j]] = se[G[x][j]][G[x][i]] = x;
        miz(v, 2);
        miz(m[G[x][j]][G[x][i]], 2);
      }
}

int minimum_cycle() {
  const int n = pr.size();
  int ans = INF;
  int d[169][169];
  memcpy(d, m, sizeof(m));
  FOR(k, n) {
    FOR(i, k)
      if (d[k][i] != INF)
        FOR(j, i) {
          if (d[k][i] == 2 && d[j][k] == 2 && se[k][i] == se[j][k]) continue;
          miz(ans, d[k][i] + m[i][j] + d[j][k]);
        }
    FOR(i, n)
      if (m[i][k] != INF)
        FOR(j, n)
          if (m[k][j] != INF)
            miz(m[i][j], m[i][k] + m[k][j]);
  }
  return ans;
}

int small_endpoint() {
  VI v;
  for(auto s: S)
    if (s < 1000)
      v.pb(M[s]);
  int ans = INF;
  FOR(i, v.size())
    FOR(j, i)
      miz(ans, 2 + m[v[j]][v[i]]);
  return ans;
}

int best_end[170];
int big_small_endpoint() {
  const int n = pr.size();
  FOR(i, n)
    best_end[i] = INF;
  VI V;
  for(auto s: S)
    if (s < 1000)
      V.pb(M[s]);
  FOR(i, n)
    for(auto v: V)
      miz(best_end[i], 1 + m[i][v]);

  int ans = INF;
  for(auto s: S)
    if (s > 1000)
      for(auto y: G[M[s]])
        miz(ans, 2 + best_end[y]);

  return ans;
}

int big_big_endpoint() {
  int ans = INF;
  static int has_bee[170];
  for(auto e: E)
    if (e.Y > 1000 && S.count(e.Y)) {
      const int &x = M[e.X];
      if (has_bee[x] == 0)
        has_bee[x] = e.Y;
      else if (has_bee[x])
        return 4;
    }
  const int n = pr.size();
  FOR(i, n)
    if (has_bee[i])
      FOR(j, i)
        if (has_bee[j]) {
          if (has_bee[i] == has_bee[j]) continue;
          miz(ans, m[i][j] + 4);
        }
  return ans;
}

int solve() {
  int a, b;
  FOR(i, n) {
    if (A[i] == 1) return 1;

    int t = ana(A[i], a, b);
    // printf("~%d %d %d\n", t, a, b);
    if (t == 0) return 1;
    if (t == 1) {
      if (S.find(a) != S.end())
        Ans = 2;
      else S.insert(a);
    }
    else {
      assert(a < b && a && b);
      if (E.find(mpr(a, b)) != E.end())
        Ans = 2;
      else E.insert(mpr(a,b));
    }
  }
  if (Ans != INF)
    return Ans;
  discrete();
  ggraph();
  mgraph();
  int ans = Ans;
  miz(ans, minimum_cycle());
  miz(ans, small_endpoint());
  miz(ans, big_small_endpoint());
  miz(ans, big_big_endpoint());

  if (ans == INF)
    return -1;
  return ans;
}

int main() {
  prime();
  R(n);
  FOR(i,n)
    R(A[i]);
  printf("%d\n", solve());
  return 0;
}

/*
3 2 2018 1009
3 2018 5045 10
5 1009 1013 3027 15 5065
5 2 2018 3027 3039 1013
3 6 2018 3027
4 2018 3027 3039 2026
4 1009 2018 3 3027 # 3
5 2018 1009 3039 1013 6
4 2018 2026 1009 1013
2 1009 2018
5 3 5 2018 3027 10
3 2018 3027 1009 # -1
6 1009 2018 2026 3039 3057 1019
6 1009 1013 2018 3027 15 5065 # 5
3 2018 3027 5045
 */


// by david942j
// {{{
#include <cstdio>
#include <cstring>
#include <set>
#include <map>
#include <ctime>
#include <vector>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <deque>
#include <cassert>
#include <queue>
#include <stack>
#include <cstdlib>
// #ifndef DAVID
// #include <bits/stdc++.h>
// #endif
#define openfile(s) freopen(s".in","r",stdin);freopen(s".out","w",stdout)
#define mpr std::make_pair
#define lg(x) (31-__builtin_clz(x))
#define lgll(x) (63-__builtin_clzll(x))
#define __count __builtin_popcount
#define __countll __builtin_popcountll
#define X first
#define Y second
#define mst(x) memset(x,0,sizeof(x))
#define mst1(x) memset(x,-1,sizeof(x))
#define ALL(c) (c).begin(),(c).end()
#define FOR(i,n) for(int i=0;i<n;i++)
#define FOR1(i,n) for(int i=1;i<=n;i++)
#define FORit(it,c) for(__typeof(c.begin()) it=c.begin();it!=c.end();++it)
#define pb push_back
#define RI(x) scanf("%d",&x)
#define RID(x) int x;RI(x)

#define IOS do {ios_base::sync_with_stdio(false); cin.tie(0); }while(0)
using namespace std;
template<typename T>
void _R( T &x ) { cin>>x; }
void _R( int &x ) { scanf("%d",&x); }
#ifdef PRId64
void _R( long long &x ) { scanf("%" PRId64,&x); }
#else
void _R( long long &x) {cin >> x;}
#endif
void _R( double &x ) { scanf("%lf",&x); }
void _R( char &x ) { scanf(" %c",&x); }
void _R( char *x ) { scanf("%s",x); }

void R() {}
template<typename T, typename... U>
void R( T& head, U&... tail ) {
  _R(head);
  R(tail...);
}

template<typename T>
void _W( const T &x ) { cout<<x; }
void _W( const int &x ) { printf("%d",x); }
template<typename T>
void _W( const vector<T> &x ) {
  for ( auto i=x.cbegin(); i!=x.cend(); i++ ) {
    if ( i!=x.cbegin() ) putchar(' ');
    _W(*i);
  }
}

void W() {}
template<typename T, typename... U>
void W( const T& head, const U&... tail ) {
  _W(head);
  putchar(sizeof...(tail)?' ':'\n');
  W(tail...);
}
#ifdef DAVID
#define debug(format, ...) fprintf(stderr, format, ##__VA_ARGS__)
#else
#define debug(...)
#endif
#define caset RID(T);FOR1(cas,T)
typedef long long LL;
typedef double LD;
typedef vector<int> VI;
typedef std::pair<int,int> PII;
template<class T>inline void maz(T &a,T b){if(a<b)a=b;}
template<class T>inline void miz(T &a,T b){if(a>b)a=b;}
template<class T>inline T abs(T a){return a>0?a:-a;}
// }}}

const int N = 1e5+10;
const int INF = 1e9+7;
const int MOD = 1e9+7;
int n;
int A[N];
VI pr;

set<int> S;
set<PII> E;

void prime() {
  static bool a[1000];
  for(int i=2;i<1000;i++) {
    if (!a[i]) {
      pr.pb(i);
      for (int j=i*i;j < 1000; j+=i)
        a[j]=1;
    }
  }
  // W(pr.size());
  // W(pr);
}

int ana(int v, int &a, int &b) {
  a = b = 0;
  for (auto p: pr)
    if (v % p == 0) {
      int k = 0;
      do {
        v /= p;
        k++;
      } while (v % p == 0);
      if (k & 1) {
        if (a == 0) a = p;
        else b = p;
      }
    }
    else if (v == 1) break;

  if (v != 1) {
    if (a == 0) a = v;
    else b = v;
  }
  if (a == 0) return 0;
  if (b == 0) return 1;
  return 2;
}

map<int, int> M;
int m[169][169];
VI G[200000];
void discrete() {
  FOR(i, pr.size())
    M[pr[i]] = i;

  int cur = pr.size();
  for(auto s: S)
    if (s > 1000 && M.count(s) == 0)
      M[s] = cur++;
  for(auto e: E) {
    assert(! (e.X > 1000 && M.count(e.X) == 0));
    if (e.Y > 1000 && M.count(e.Y) == 0)
      M[e.Y] = cur++;
  }
}

void ggraph() {
  for(auto e: E)
    if (e.Y > 1000) {
      G[M[e.Y]].pb(M[e.X]);
    }
}

void mgraph() {
  const int n = pr.size();

  FOR(i, n) {
    FOR(j, i)
      m[i][j] = m[j][i] = INF;
    m[i][i] = 0;
  }
  for(auto e: E) {
    const int &x = M[e.X], &y = M[e.Y];
    if (x < n && y < n)
      m[x][y] = m[y][x] = 1;
  }
}

void floyd() {
  mgraph();
  const int n = pr.size();

  FOR(k, n)
    FOR(i, n)
      FOR(j, n)
        if (m[i][k] != INF && m[k][j] != INF)
          miz(m[i][j], m[i][k] + m[k][j]);
}

int BFS(int x, int y) {
  queue<int> Q;
  const int n = pr.size();
  int dis[170];
  FOR(i, n)
    dis[i] = INF;
  Q.push(x); dis[x] = 0;
  while (!Q.empty()) {
    auto a = Q.front(); Q.pop();
    FOR(i, n)
      if (m[a][i] == 1 && dis[i] == INF) {
        dis[i] = dis[a] + 1;
        if (y == i)
          return dis[y];
        Q.push(i);
      }
  }

  return INF;
}

int small_cycle() {
  mgraph();
  const int n = pr.size();
  int ans = INF;
  FOR(i, n)
    FOR(j, i)
      if (m[j][i] == 1) {
        m[j][i] = m[i][j] = INF;
        int len = BFS(i, j);
        m[j][i] = m[i][j] = 1;
        miz(ans, len + 1);
      }
  return ans;
}

int small_endpoint() {
  VI v;
  for(auto s: S)
    if (s < 1000)
      v.pb(M[s]);
  int ans = INF;
  FOR(i, v.size())
    FOR(j, i)
      miz(ans, 2 + m[v[j]][v[i]]);
  return ans;
}

int big_cycle() {
  int ans = INF;
  FOR(x, 110000)
    FOR(i, G[x].size())
      FOR(j, i)
        miz(ans, m[G[x][i]][G[x][j]] + 2);
  return ans;
}

int big_small_endpoint() {
  static int best_end[170];
  const int n = pr.size();
  FOR(i, n)
    best_end[i] = INF;
  VI V;
  for(auto s: S)
    if (s < 1000)
      V.pb(M[s]);
  FOR(i, n)
    for(auto v: V)
      miz(best_end[i], 1 + m[i][v]);

  int ans = INF;
  for(auto s: S)
    if (s > 1000)
      for(auto y: G[M[s]])
        miz(ans, 2 + best_end[y]);

  return ans;
}

int big_big_endpoint() {
  int ans = INF;
  static bool has_bee[170];
  for(auto e: E)
    if (e.Y > 1000 && S.count(e.Y))
      has_bee[M[e.X]] = true;
  const int n = pr.size();
  FOR(i, n)
      if (has_bee[i])
        FOR(j, i)
          if (has_bee[j])
            miz(ans, m[i][j] + 4);
  return ans;
}

int solve() {
  int a, b;
  FOR(i, n) {
    if (A[i] == 1) return 1;

    int t = ana(A[i], a, b);
    // printf("~%d %d %d\n", t, a, b);
    if (t == 0) return 1;
    if (t == 1) {
      if (S.find(a) != S.end())
        return 2;
      else S.insert(a);
    }
    else {
      if (E.find(mpr(a, b)) != E.end())
        return 2;
      else E.insert(mpr(a,b));
    }
  }
  discrete();
  int ans = INF;
  miz(ans, small_cycle());
  floyd();
  miz(ans, small_endpoint());
  ggraph();
  miz(ans, big_small_endpoint());
  miz(ans, big_big_endpoint());
  miz(ans, big_cycle());

  if (ans == INF)
    return -1;
  return ans;
}

int main() {
  prime();
  R(n);
  FOR(i,n)
    R(A[i]);
  printf("%d\n", solve());
  return 0;
}

/*
3 2 2006 1003
4 2 2006 1003 17
3 2 2018 1009
3 2018 5045 10
5 1009 1013 3027 15 5065
 */


#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
//#pragma GCC optimization ("unroll-loops")
//#pragma comment(linker, "/STACK:16777216")

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/priority_queue.hpp>

using namespace std;
using namespace __gnu_pbds;

#define LL long long
#define int long long
#define fi first
#define se second
#define pll pair<LL, LL>
#define pii pair<LL, LL>
#define fastio ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define SZ(x) ((int)(x.size()))
#define LC (id<<1)
#define RC (id<<1|1)

constexpr int N = 1e6+9;
constexpr int M = 3e3+6 ;
#ifdef int
constexpr int INF = 0x3f3f3f3f3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcfcfcfcfcf;
#else
constexpr int INF = 0x3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcf;
#endif

int n;
int x, tot;
int pos[N];
int node[N];
vector<int> g[N];
bool prime[N];
vector<int> primes;
int ans = INF;

void init() {
    memset(prime, 1, sizeof(prime));
    prime[0] = prime[1] = false;
    for (int i = 2; i < N; i++) {
        if (!prime[i]) continue;
        primes.emplace_back(i);
        for (int j = i*i; j < N; j += i)
            prime[j] = false;
    }
}

void addEdge(int u, int v) {
    if (!pos[u]) pos[u] = ++tot, node[tot] = u;
    if (!pos[v]) pos[v] = ++tot, node[tot] = v;
    g[pos[u]].emplace_back(pos[v]);
    g[pos[v]].emplace_back(pos[u]);
}

int dis[N];

int bfs(int s) {
    memset(dis, 0x3f, sizeof(dis));
    queue<int> q;
    q.emplace(s);
    dis[s] = 0;
    int res = INF;
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        for (int v: g[u]) {
            if (dis[v] > dis[u] + 1)
                q.emplace(v), dis[v] = dis[u] + 1;
            else
                res = min(res, dis[u] + 1 + dis[v]);
        }
    }
    return res;
}

signed main() {
    fastio;
    init();
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> x;
        pii ps = {1, 1};
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.fi = p;
                break;
            }
        }
        if (ps.fi == 1 && x != 1)
            ps.fi = x, x /= x;
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.se = p;
                break;
            }
        }
        if (ps.se == 1 && x != 1)
            ps.se = x, x /= x;
        if (ps.fi == 1 && ps.se == 1)
            ans = 1;
        else
            addEdge(ps.fi, ps.se);
    }
    for (int i = 1; i <= 1000; i++)
        if (pos[i]) ans = min(ans, bfs(pos[i]));
    cout << (ans < INF ? ans : -1) << "\n";
    return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
//#pragma GCC optimization ("unroll-loops")
//#pragma comment(linker, "/STACK:16777216")

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/priority_queue.hpp>

using namespace std;
using namespace __gnu_pbds;

#define LL long long
#define int long long
#define fi first
#define se second
#define pll pair<LL, LL>
#define pii pair<LL, LL>
#define fastio ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define SZ(x) ((int)(x.size()))
#define LC (id<<1)
#define RC (id<<1|1)

constexpr int N = 1e6+9;
constexpr int M = 3e3+6 ;
#ifdef int
constexpr int INF = 0x3f3f3f3f3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcfcfcfcfcf;
#else
constexpr int INF = 0x3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcf;
#endif

int n;
int x, tot;
int pos[N];
int node[N];
int g[M][M];
bool prime[N];
vector<int> primes;
int ans = INF;

void init() {
    memset(prime, 1, sizeof(prime));
    prime[0] = prime[1] = false;
    for (int i = 2; i < N; i++) {
        if (!prime[i]) continue;
        primes.emplace_back(i);
        for (int j = i*i; j < N; j += i)
            prime[j] = false;
    }
}

void addEdge(int u, int v) {
    if (u > 1000 || v > 1000) return;
    //cout << u << " " << v << "\n";
    if (!pos[u]) pos[u] = ++tot, node[tot] = u;
    if (!pos[v]) pos[v] = ++tot, node[tot] = v;
    g[pos[u]][pos[v]]++;
    g[pos[v]][pos[u]]++;
    if (g[pos[u]][pos[v]] > 1)
        ans = min(ans, 2ll);
}

void floyd() {
    for (int i = 1; i <= tot; i++)
        for (int j = 1; j <= tot; j++)
            if (g[i][j] == 0) g[i][j] = INF;
    static int dis[M][M];  // 最短路矩阵
    for (int i = 1; i <= tot; ++i)
        for (int j = 1; j <= tot; ++j) dis[i][j] = g[i][j];  // 初始化最短路矩阵
    for (int k = 1; k <= tot; ++k) {
        for (int i = 1; i < k; ++i)
            for (int j = 1; j < i; ++j)
                ans = min(ans, dis[i][j] + g[i][k] + g[k][j]);  // 更新答案
        for (int i = 1; i <= tot; ++i)
            for (int j = 1; j <= tot; ++j) {
                dis[i][j] = std::min(
                        dis[i][j], dis[i][k] + dis[k][j]);  // 正常的 floyd 更新最短路矩阵
            }
    }
}

signed main() {
    fastio;
    init();
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> x;
        pii ps = {1, 1};
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.fi = p;
                break;
            }
        }
        if (ps.fi == 1 && x != 1)
            ps.fi = x, x /= x;
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.se = p;
                break;
            }
        }
        if (ps.se == 1 && x != 1)
            ps.se = x, x /= x;
        if (ps.fi == 1 && ps.se == 1)
            ans = 1;
        else
            addEdge(ps.fi, ps.se);
    }
    if (ans != INF) cout << ans << "\n";
    else floyd(), cout << (ans < INF ? ans : -1) << "\n";
    return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
//#pragma GCC optimization ("unroll-loops")
//#pragma comment(linker, "/STACK:16777216")

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/priority_queue.hpp>

using namespace std;
using namespace __gnu_pbds;

#define LL long long
#define int long long
#define fi first
#define se second
#define pll pair<LL, LL>
#define pii pair<LL, LL>
#define fastio ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define SZ(x) ((int)(x.size()))
#define LC (id<<1)
#define RC (id<<1|1)

constexpr int N = 1e6+9;
constexpr int M = 3e3+6 ;
#ifdef int
constexpr int INF = 0x3f3f3f3f3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcfcfcfcfcf;
#else
constexpr int INF = 0x3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcf;
#endif

int n;
int x, tot;
int pos[N];
int node[N];
int g[M][M];
bool prime[N];
vector<int> maxi[N];
vector<int> primes;
int ans = INF;

void init() {
    memset(prime, 1, sizeof(prime));
    prime[0] = prime[1] = false;
    for (int i = 2; i < N; i++) {
        if (!prime[i]) continue;
        primes.emplace_back(i);
        for (int j = i*i; j < N; j += i)
            prime[j] = false;
    }
}

void addEdge(int u, int v) {
    if (u > v) swap(u, v);
    if (v > 1000) {
        assert(prime[v]);
        maxi[v].emplace_back(u);
        if (!pos[u]) pos[u] = ++tot, node[tot] = u;
        return;
    }
    if (!pos[u]) pos[u] = ++tot, node[tot] = u;
    if (!pos[v]) pos[v] = ++tot, node[tot] = v;
    if (g[pos[u]][pos[v]] == 1)
        ans = min(ans, 2ll);
    g[pos[u]][pos[v]] = 1;
    g[pos[v]][pos[u]] = 1;
}

void floyd() {
    for (int i = 1; i <= tot; i++)
        for (int j = 1; j <= tot; j++)
            if (g[i][j] == 0 && i != j) g[i][j] = INF;
    for (int t = 1; t < N; t++) {
        for (int i = 0; i < SZ(maxi[t]); i++)
            for (int j = i+1; j < SZ(maxi[t]); j++) {
                int u = maxi[t][i];
                int v = maxi[t][j];
                if (u == v) {
                    ans = min(ans, 2ll);
                    continue;
                }
                if (g[pos[u]][pos[v]] < INF) {
                    ans = min(ans, g[pos[u]][pos[v]] + 2);
                    continue;
                }
                g[pos[u]][pos[v]] = min(g[pos[u]][pos[v]], 2ll);
                g[pos[v]][pos[u]] = min(g[pos[v]][pos[u]], 2ll);
            }
    }
    static int dis[M][M];  // 最短路矩阵
    for (int i = 1; i <= tot; ++i)
        for (int j = 1; j <= tot; ++j) dis[i][j] = g[i][j];  // 初始化最短路矩阵
    for (int k = 1; k <= tot; ++k) {
        for (int i = 1; i < k; ++i)
            for (int j = 1; j < i; ++j)
                ans = min(ans, dis[i][j] + min(INF, g[i][k] + g[k][j]));  // 更新答案
        for (int i = 1; i <= tot; ++i)
            for (int j = 1; j <= tot; ++j) {
                dis[i][j] = std::min(
                        dis[i][j], dis[i][k] + dis[k][j]);  // 正常的 floyd 更新最短路矩阵
            }
    }
}

signed main() {
    fastio;
    init();
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> x;
        pii ps = {1, 1};
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.fi = p;
                break;
            }
        }
        if (ps.fi == 1 && x != 1)
            ps.fi = x, x /= x;
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.se = p;
                break;
            }
        }
        if (ps.se == 1 && x != 1)
            ps.se = x, x /= x;
        if (ps.fi == 1 && ps.se == 1)
            ans = 1;
        else
            addEdge(ps.fi, ps.se);
    }
    if (ans != INF) cout << ans << "\n";
    else floyd(), cout << (ans < INF ? ans : -1) << "\n";
    return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
//#pragma GCC optimization ("unroll-loops")
//#pragma comment(linker, "/STACK:16777216")

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/priority_queue.hpp>

using namespace std;
using namespace __gnu_pbds;

#define LL long long
#define int long long
#define fi first
#define se second
#define pll pair<LL, LL>
#define pii pair<LL, LL>
#define fastio ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define SZ(x) ((int)(x.size()))
#define LC (id<<1)
#define RC (id<<1|1)

constexpr int N = 1e6+9;
constexpr int M = 3e3+6 ;
#ifdef int
constexpr int INF = 0x3f3f3f3f3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcfcfcfcfcf;
#else
constexpr int INF = 0x3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcf;
#endif

int n;
int x, tot;
int pos[N];
int node[N];
int g[M][M];
bool prime[N];
vector<int> primes;
int ans = INF;

void init() {
    memset(prime, 1, sizeof(prime));
    prime[0] = prime[1] = false;
    for (int i = 2; i < N; i++) {
        if (!prime[i]) continue;
        primes.emplace_back(i);
        for (int j = i*i; j < N; j += i)
            prime[j] = false;
    }
}

void addEdge(int u, int v) {
    if (u > 1000 || v > 1000) return;
    //cout << u << " " << v << "\n";
    if (!pos[u]) pos[u] = ++tot, node[tot] = u;
    if (!pos[v]) pos[v] = ++tot, node[tot] = v;
    g[pos[u]][pos[v]]++;
    g[pos[v]][pos[u]]++;
    if (g[pos[u]][pos[v]] > 1)
        ans = min(ans, 2ll);
}

void floyd() {
    for (int i = 1; i <= tot; i++)
        for (int j = 1; j <= tot; j++)
            if (!g[i][j]) g[i][j] = 1e9;
    static int dis[M][M];  // 最短路矩阵
    for (int i = 1; i <= tot; ++i)
        for (int j = 1; j <= tot; ++j) dis[i][j] = g[i][j];  // 初始化最短路矩阵
    for (int k = 1; k <= tot; ++k) {
        for (int i = 1; i < k; ++i)
            for (int j = 1; j < i; ++j)
                ans = min(ans, dis[i][j] + g[i][k] + g[k][j]);  // 更新答案
        for (int i = 1; i <= tot; ++i)
            for (int j = 1; j <= tot; ++j)
                dis[i][j] = std::min(
                        dis[i][j], dis[i][k] + dis[k][j]);  // 正常的 floyd 更新最短路矩阵
    }
}

signed main() {
    fastio;
    init();
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> x;
        pii ps = {1, 1};
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.fi = p;
                break;
            }
        }
        if (ps.fi == 1 && x != 1)
            ps.fi = x, x /= x;
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.se = p;
                break;
            }
        }
        if (ps.se == 1 && x != 1)
            ps.se = x, x /= x;
        if (ps.fi == 1 && ps.se == 1)
            ans = 1;
        else
            addEdge(ps.fi, ps.se);
    }
    if (ans != INF) cout << ans << "\n";
    else floyd(), cout << (ans < 1e9 ? ans : -1) << "\n";
    return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
//#pragma GCC optimization ("unroll-loops")
//#pragma comment(linker, "/STACK:16777216")

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/priority_queue.hpp>

using namespace std;
using namespace __gnu_pbds;

#define LL long long
#define int long long
#define fi first
#define se second
#define pll pair<LL, LL>
#define pii pair<LL, LL>
#define fastio ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define SZ(x) ((int)(x.size()))
#define LC (id<<1)
#define RC (id<<1|1)

constexpr int N = 1e6+9;
constexpr int M = 1e3+6 ;
#ifdef int
constexpr int INF = 0x3f3f3f3f3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcfcfcfcfcf;
#else
constexpr int INF = 0x3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcf;
#endif

int n;
int x, tot;
int pos[N];
int node[N];
int g[M][M];
bool prime[N];
vector<int> primes;
int ans = INF;
int vis[M][M];

void init() {
    memset(prime, 1, sizeof(prime));
    prime[0] = prime[1] = false;
    for (int i = 2; i < N; i++) {
        if (!prime[i]) continue;
        primes.emplace_back(i);
        for (int j = i*i; j < N; j += i)
            prime[j] = false;
    }
}

void addEdge(int u, int v) {
    if (!pos[u]) pos[u] = ++tot, node[tot] = u;
    if (!pos[v]) pos[v] = ++tot, node[tot] = v;
    g[pos[u]][pos[v]]++;
    g[pos[v]][pos[u]]++;
    if (g[pos[u]][pos[v]] > 1)
        ans = min(ans, 2ll);
}

void floyd() {
    for (int i = 1; i <= tot; i++)
        for (int j = 1; j <= tot; j++)
            if (!g[i][j]) g[i][j] = INF;
    static int dis[M][M];  // 最短路矩阵
    for (int i = 1; i <= tot; ++i)
        for (int j = 1; j <= tot; ++j) dis[i][j] = g[i][j];  // 初始化最短路矩阵
    for (int k = 1; k <= tot; ++k) {
        for (int i = 1; i < k; ++i)
            for (int j = 1; j < i; ++j)
                ans = min(ans, dis[i][j] + g[i][k] + g[k][j]);  // 更新答案
        for (int i = 1; i <= n; ++i)
            for (int j = 1; j <= n; ++j)
                dis[i][j] = std::min(
                        dis[i][j], dis[i][k] + dis[k][j]);  // 正常的 floyd 更新最短路矩阵
    }
}

signed main() {
    fastio;
    init();
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> x;
        pii ps = {1, 1};
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) ps.fi = p;
        }
        if (x != 1) ps.se = x;
        if (ps.fi == 1 && ps.se == 1)
            ans = 1;
        else
            addEdge(ps.fi, ps.se);
    }
    if (ans != INF) cout << ans << "\n";
    else floyd(), cout << (ans < INF ? ans : -1) << "\n";
    return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
//#pragma GCC optimization ("unroll-loops")
//#pragma comment(linker, "/STACK:16777216")

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/priority_queue.hpp>

using namespace std;
using namespace __gnu_pbds;

#define LL long long
#define int long long
#define fi first
#define se second
#define pll pair<LL, LL>
#define pii pair<LL, LL>
#define fastio ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define SZ(x) ((int)(x.size()))
#define LC (id<<1)
#define RC (id<<1|1)

constexpr int N = 1e6+9;
constexpr int M = 3e3+6 ;
#ifdef int
constexpr int INF = 0x3f3f3f3f3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcfcfcfcfcf;
#else
constexpr int INF = 0x3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcf;
#endif

int n;
int x, tot;
int pos[N];
int node[N];
int g[M][M];
bool prime[N];
map<int, vector<int>> maxi;
vector<int> primes;
int ans = INF;

void init() {
    memset(prime, 1, sizeof(prime));
    prime[0] = prime[1] = false;
    for (int i = 2; i < N; i++) {
        if (!prime[i]) continue;
        primes.emplace_back(i);
        for (int j = i*i; j < N; j += i)
            prime[j] = false;
    }
}

void addEdge(int u, int v) {
    if (u > v) swap(u, v);
    if (v > 1000) {
        if (u > 1)
            maxi[v].emplace_back(u);
        return;
    }
    if (!pos[u]) pos[u] = ++tot, node[tot] = u;
    if (!pos[v]) pos[v] = ++tot, node[tot] = v;
    g[pos[u]][pos[v]]++;
    g[pos[v]][pos[u]]++;
    if (g[pos[u]][pos[v]] > 1)
        ans = min(ans, 2ll);
}

void floyd() {
    for (const auto& p: maxi) {
        for (int i = 0; i < SZ(p.se); i++)
            for (int j = i+1; j < SZ(p.se); j++)
                g[pos[i]][pos[j]] = min(g[pos[i]][pos[j]], 2ll);
    }
    for (int i = 1; i <= tot; i++)
        for (int j = 1; j <= tot; j++)
            if (g[i][j] == 0) g[i][j] = INF;
    static int dis[M][M];  // 最短路矩阵
    for (int i = 1; i <= tot; ++i)
        for (int j = 1; j <= tot; ++j) dis[i][j] = g[i][j];  // 初始化最短路矩阵
    for (int k = 1; k <= tot; ++k) {
        for (int i = 1; i < k; ++i)
            for (int j = 1; j < i; ++j)
                ans = min(ans, dis[i][j] + min(INF, g[i][k] + g[k][j]));  // 更新答案
        for (int i = 1; i <= tot; ++i)
            for (int j = 1; j <= tot; ++j) {
                dis[i][j] = std::min(
                        dis[i][j], dis[i][k] + dis[k][j]);  // 正常的 floyd 更新最短路矩阵
            }
    }
}

signed main() {
    fastio;
    init();
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> x;
        pii ps = {1, 1};
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.fi = p;
                break;
            }
        }
        if (ps.fi == 1 && x != 1)
            ps.fi = x, x /= x;
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.se = p;
                break;
            }
        }
        if (ps.se == 1 && x != 1)
            ps.se = x, x /= x;
        if (ps.fi == 1 && ps.se == 1)
            ans = 1;
        else
            addEdge(ps.fi, ps.se);
    }
    if (ans != INF) cout << ans << "\n";
    else floyd(), cout << (ans < INF ? ans : -1) << "\n";
    return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
//#pragma GCC optimization ("unroll-loops")
//#pragma comment(linker, "/STACK:16777216")

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/priority_queue.hpp>

using namespace std;
using namespace __gnu_pbds;

#define LL long long
#define int long long
#define fi first
#define se second
#define pll pair<LL, LL>
#define pii pair<LL, LL>
#define fastio ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define SZ(x) ((int)(x.size()))
#define LC (id<<1)
#define RC (id<<1|1)

constexpr int N = 1e6+9;
constexpr int M = 3e3+6 ;
#ifdef int
constexpr int INF = 0x3f3f3f3f3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcfcfcfcfcf;
#else
constexpr int INF = 0x3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcf;
#endif

int n;
int x, tot;
int pos[N];
int node[N];
int g[M][M];
bool prime[N];
vector<int> primes;
int ans = INF;

void init() {
    memset(prime, 1, sizeof(prime));
    prime[0] = prime[1] = false;
    for (int i = 2; i < N; i++) {
        if (!prime[i]) continue;
        primes.emplace_back(i);
        for (int j = i*i; j < N; j += i)
            prime[j] = false;
    }
}

void addEdge(int u, int v) {
    if (u > 1000 || v > 1000) return;
    //cout << u << " " << v << "\n";
    if (!pos[u]) pos[u] = ++tot, node[tot] = u;
    if (!pos[v]) pos[v] = ++tot, node[tot] = v;
    g[pos[u]][pos[v]]++;
    g[pos[v]][pos[u]]++;
    if (g[pos[u]][pos[v]] > 1)
        ans = min(ans, 2ll);
}

void floyd() {
    int INf = 1e9;
    for (int i = 1; i <= tot; i++)
        for (int j = 1; j <= tot; j++)
            if (!g[i][j]) g[i][j] = 1e9;
    static int dis[M][M];  // 最短路矩阵
    for (int i = 1; i <= tot; ++i)
        for (int j = 1; j <= tot; ++j) dis[i][j] = g[i][j];  // 初始化最短路矩阵
    for (int k = 1; k <= tot; ++k) {
        for (int i = 1; i < k; ++i)
            for (int j = 1; j < i; ++j)
                ans = min(ans, dis[i][j] + min(INf, g[i][k] + g[k][j]));  // 更新答案
        for (int i = 1; i <= tot; ++i)
            for (int j = 1; j <= tot; ++j)
                dis[i][j] = std::min(
                        dis[i][j], dis[i][k] + dis[k][j]);  // 正常的 floyd 更新最短路矩阵
    }
}

signed main() {
    fastio;
    init();
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> x;
        pii ps = {1, 1};
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.fi = p;
                break;
            }
        }
        if (ps.fi == 1 && x != 1)
            ps.fi = x, x /= x;
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.se = p;
                break;
            }
        }
        if (ps.se == 1 && x != 1)
            ps.se = x, x /= x;
        if (ps.fi == 1 && ps.se == 1)
            ans = 1;
        else
            addEdge(ps.fi, ps.se);
    }
    if (ans != INF) cout << ans << "\n";
    else floyd(), cout << (ans < 1e9 ? ans : -1) << "\n";
    return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
//#pragma GCC optimization ("unroll-loops")
//#pragma comment(linker, "/STACK:16777216")

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/priority_queue.hpp>

using namespace std;
using namespace __gnu_pbds;

#define LL long long
#define int long long
#define fi first
#define se second
#define pll pair<LL, LL>
#define pii pair<LL, LL>
#define fastio ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define SZ(x) ((int)(x.size()))
#define LC (id<<1)
#define RC (id<<1|1)

constexpr int N = 1e6+9;
constexpr int M = 3e3+6 ;
#ifdef int
constexpr int INF = 0x3f3f3f3f3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcfcfcfcfcf;
#else
constexpr int INF = 0x3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcf;
#endif

int n;
int x, tot;
int pos[N];
int node[N];
int g[M][M];
bool prime[N];
vector<int> maxi[N];
vector<int> primes;
int ans = INF;

void init() {
    memset(prime, 1, sizeof(prime));
    prime[0] = prime[1] = false;
    for (int i = 2; i < N; i++) {
        if (!prime[i]) continue;
        primes.emplace_back(i);
        for (int j = i*i; j < N; j += i)
            prime[j] = false;
    }
}

void addEdge(int u, int v) {
    if (u > v) swap(u, v);
    if (v > 1000) {
        assert(prime[v]);
        maxi[v].emplace_back(u);
        if (!pos[u]) pos[u] = ++tot, node[tot] = u;
        return;
    }
    if (!pos[u]) pos[u] = ++tot, node[tot] = u;
    if (!pos[v]) pos[v] = ++tot, node[tot] = v;
    if (g[pos[u]][pos[v]] == 1)
        ans = min(ans, 2ll);
    g[pos[u]][pos[v]] = 1;
    g[pos[v]][pos[u]] = 1;
}

void floyd() {
    for (int i = 1; i <= tot; i++)
        for (int j = 1; j <= tot; j++)
            if (g[i][j] == 0 && i != j) g[i][j] = INF;
    for (int t = 1; t < N; t++) {
        for (int i = 0; i < SZ(maxi[t]); i++)
            for (int j = 0; j < SZ(maxi[t]); j++) {
                if (i == j) continue;
                int u = maxi[t][i];
                int v = maxi[t][j];
                if (u == v) {
                    ans = min(ans, 2ll);
                    continue;
                }
                if (g[pos[u]][pos[v]] < INF) {
                    ans = min(ans, g[pos[u]][pos[v]] + 2);
                    continue;
                }
                g[pos[u]][pos[v]] = min(g[pos[u]][pos[v]], 2ll);
                g[pos[v]][pos[u]] = min(g[pos[v]][pos[u]], 2ll);
            }
    }
    static int dis[M][M];  // 最短路矩阵
    for (int i = 1; i <= tot; ++i)
        for (int j = 1; j <= tot; ++j) dis[i][j] = g[i][j];  // 初始化最短路矩阵
    for (int k = 1; k <= tot; ++k) {
        for (int i = 1; i < k; ++i)
            for (int j = 1; j < i; ++j)
                ans = min(ans, dis[i][j] + min(INF, g[i][k] + g[k][j]));  // 更新答案
        for (int i = 1; i <= tot; ++i)
            for (int j = 1; j <= tot; ++j) {
                dis[i][j] = std::min(
                        dis[i][j], dis[i][k] + dis[k][j]);  // 正常的 floyd 更新最短路矩阵
            }
    }
}

signed main() {
    fastio;
    init();
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> x;
        pii ps = {1, 1};
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.fi = p;
                break;
            }
        }
        if (ps.fi == 1 && x != 1)
            ps.fi = x, x /= x;
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.se = p;
                break;
            }
        }
        if (ps.se == 1 && x != 1)
            ps.se = x, x /= x;
        if (ps.fi == 1 && ps.se == 1)
            ans = 1;
        else
            addEdge(ps.fi, ps.se);
    }
    if (ans != INF) cout << ans << "\n";
    else floyd(), cout << (ans < INF ? ans : -1) << "\n";
    return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
//#pragma GCC optimization ("unroll-loops")
//#pragma comment(linker, "/STACK:16777216")

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/priority_queue.hpp>

using namespace std;
using namespace __gnu_pbds;

#define LL long long
#define int long long
#define fi first
#define se second
#define pll pair<LL, LL>
#define pii pair<LL, LL>
#define fastio ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define SZ(x) ((int)(x.size()))
#define LC (id<<1)
#define RC (id<<1|1)

constexpr int N = 1e6+9;
constexpr int M = 3e3+6 ;
#ifdef int
constexpr int INF = 0x3f3f3f3f3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcfcfcfcfcf;
#else
constexpr int INF = 0x3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcf;
#endif

int n;
int x, tot;
int pos[N];
int node[N];
int g[M][M];
bool prime[N];
vector<int> maxi[N];
vector<int> primes;
int ans = INF;

void init() {
    memset(prime, 1, sizeof(prime));
    prime[0] = prime[1] = false;
    for (int i = 2; i < N; i++) {
        if (!prime[i]) continue;
        primes.emplace_back(i);
        for (int j = i*i; j < N; j += i)
            prime[j] = false;
    }
}

void addEdge(int u, int v) {
    if (u > v) swap(u, v);
    if (v > 1000) {
        maxi[v].emplace_back(u);
        if (!pos[u]) pos[u] = ++tot, node[tot] = u;
        return;
    }
    if (!pos[u]) pos[u] = ++tot, node[tot] = u;
    if (!pos[v]) pos[v] = ++tot, node[tot] = v;
    g[pos[u]][pos[v]]++;
    g[pos[v]][pos[u]]++;
    if (g[pos[u]][pos[v]] > 1)
        ans = min(ans, 2ll);
}

void floyd() {
    for (int i = 1; i <= tot; i++)
        for (int j = 1; j <= tot; j++)
            if (g[i][j] == 0 && i != j) g[i][j] = INF;
    for (int t = 1; t < N; t++)
        for (int i = 0; i < SZ(maxi[t]); i++)
            for (int j = 0; j < SZ(maxi[t]); j++) {
                if (i == j) continue;
                int u = maxi[t][i];
                int v = maxi[t][j];
                if (u == v) {
                    ans = min(ans, 2ll);
                    continue;
                }
                if (g[pos[u]][pos[v]] < INF) {
                    ans = min(ans, 3ll);
                    continue;
                }
                g[pos[u]][pos[v]] = 2;
            }
    static int dis[M][M];  // 最短路矩阵
    for (int i = 1; i <= tot; ++i)
        for (int j = 1; j <= tot; ++j) dis[i][j] = g[i][j];  // 初始化最短路矩阵
    for (int k = 1; k <= tot; ++k) {
        for (int i = 1; i < k; ++i)
            for (int j = 1; j < i; ++j)
                ans = min(ans, dis[i][j] + min(INF, g[i][k] + g[k][j]));  // 更新答案
        for (int i = 1; i <= tot; ++i)
            for (int j = 1; j <= tot; ++j) {
                dis[i][j] = std::min(
                        dis[i][j], dis[i][k] + dis[k][j]);  // 正常的 floyd 更新最短路矩阵
            }
    }
}

signed main() {
    fastio;
    init();
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> x;
        pii ps = {1, 1};
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.fi = p;
                break;
            }
        }
        if (ps.fi == 1 && x != 1)
            ps.fi = x, x /= x;
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.se = p;
                break;
            }
        }
        if (ps.se == 1 && x != 1)
            ps.se = x, x /= x;
        if (ps.fi == 1 && ps.se == 1)
            ans = 1;
        else
            addEdge(ps.fi, ps.se);
    }
    if (ans != INF) cout << ans << "\n";
    else floyd(), cout << (ans < INF ? ans : -1) << "\n";
    return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
//#pragma GCC optimization ("unroll-loops")
//#pragma comment(linker, "/STACK:16777216")

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/priority_queue.hpp>

using namespace std;
using namespace __gnu_pbds;

#define LL long long
#define int long long
#define fi first
#define se second
#define pll pair<LL, LL>
#define pii pair<LL, LL>
#define fastio ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define SZ(x) ((int)(x.size()))
#define LC (id<<1)
#define RC (id<<1|1)

constexpr int N = 1e6+9;
constexpr int M = 3e3+6 ;
#ifdef int
constexpr int INF = 0x3f3f3f3f3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcfcfcfcfcf;
#else
constexpr int INF = 0x3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcf;
#endif

int n;
int x, tot;
int pos[N];
int node[N];
int g[M][M];
bool prime[N];
vector<int> maxi[N];
vector<int> primes;
int ans = INF;

void init() {
    memset(prime, 1, sizeof(prime));
    prime[0] = prime[1] = false;
    for (int i = 2; i < N; i++) {
        if (!prime[i]) continue;
        primes.emplace_back(i);
        for (int j = i*i; j < N; j += i)
            prime[j] = false;
    }
}

void addEdge(int u, int v) {
    if (u > v) swap(u, v);
    if (v > 1000) {
        maxi[v].emplace_back(u);
        if (!pos[u]) pos[u] = ++tot, node[tot] = u;
        return;
    }
    if (!pos[u]) pos[u] = ++tot, node[tot] = u;
    if (!pos[v]) pos[v] = ++tot, node[tot] = v;
    if (g[pos[u]][pos[v]] == 1)
        ans = min(ans, 2ll);
    g[pos[u]][pos[v]] = 1;
    g[pos[v]][pos[u]] = 1;
}

void floyd() {
    for (int i = 1; i <= tot; i++)
        for (int j = 1; j <= tot; j++)
            if (g[i][j] == 0 && i != j) g[i][j] = INF;
    for (int t = 1; t < N; t++)
        for (int i = 0; i < SZ(maxi[t]); i++)
            for (int j = 0; j < SZ(maxi[t]); j++) {
                if (i == j) continue;
                int u = maxi[t][i];
                int v = maxi[t][j];
                if (u == v) {
                    ans = min(ans, 2ll);
                    continue;
                }
                if (g[pos[u]][pos[v]] < INF) {
                    ans = min(ans, g[pos[u]][pos[v]] + 2);
                    continue;
                }
                g[pos[u]][pos[v]] = min(g[pos[u]][pos[v]], 2ll);
                g[pos[v]][pos[u]] = min(g[pos[v]][pos[u]], 2ll);
            }
    static int dis[M][M];  // 最短路矩阵
    for (int i = 1; i <= tot; ++i)
        for (int j = 1; j <= tot; ++j) dis[i][j] = g[i][j];  // 初始化最短路矩阵
    for (int k = 1; k <= tot; ++k) {
        for (int i = 1; i < k; ++i)
            for (int j = 1; j < i; ++j)
                ans = min(ans, dis[i][j] + min(INF, g[i][k] + g[k][j]));  // 更新答案
        for (int i = 1; i <= tot; ++i)
            for (int j = 1; j <= tot; ++j) {
                dis[i][j] = std::min(
                        dis[i][j], dis[i][k] + dis[k][j]);  // 正常的 floyd 更新最短路矩阵
            }
    }
}

signed main() {
    fastio;
    init();
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> x;
        pii ps = {1, 1};
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.fi = p;
                break;
            }
        }
        if (ps.fi == 1 && x != 1)
            ps.fi = x, x /= x;
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.se = p;
                break;
            }
        }
        if (ps.se == 1 && x != 1)
            ps.se = x, x /= x;
        if (ps.fi == 1 && ps.se == 1)
            ans = 1;
        else
            addEdge(ps.fi, ps.se);
    }
    if (ans != INF) cout << ans << "\n";
    else floyd(), cout << (ans < INF ? ans : -1) << "\n";
    return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
//#pragma GCC optimization ("unroll-loops")
//#pragma comment(linker, "/STACK:16777216")

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/priority_queue.hpp>

using namespace std;
using namespace __gnu_pbds;

#define LL long long
#define int long long
#define fi first
#define se second
#define pll pair<LL, LL>
#define pii pair<LL, LL>
#define fastio ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define SZ(x) ((int)(x.size()))
#define LC (id<<1)
#define RC (id<<1|1)

constexpr int N = 1e6+9;
constexpr int M = 3e3+6 ;
#ifdef int
constexpr int INF = 0x3f3f3f3f3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcfcfcfcfcf;
#else
constexpr int INF = 0x3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcf;
#endif

int n;
int x, tot;
int pos[N];
int node[N];
int g[M][M];
bool prime[N];
vector<int> primes;
int ans = INF;

void init() {
    memset(prime, 1, sizeof(prime));
    prime[0] = prime[1] = false;
    for (int i = 2; i < N; i++) {
        if (!prime[i]) continue;
        primes.emplace_back(i);
        for (int j = i*i; j < N; j += i)
            prime[j] = false;
    }
}

void addEdge(int u, int v) {
    if (u > 1000 || v > 1000) return;
    //cout << u << " " << v << "\n";
    if (!pos[u]) pos[u] = ++tot, node[tot] = u;
    if (!pos[v]) pos[v] = ++tot, node[tot] = v;
    g[pos[u]][pos[v]]++;
    g[pos[v]][pos[u]]++;
    if (g[pos[u]][pos[v]] > 1)
        ans = min(ans, 2ll);
}

void floyd() {
    int INf = 1e9;
    for (int i = 1; i <= tot; i++)
        for (int j = 1; j <= tot; j++)
            if (g[i][j] == 0) g[i][j] = 1e9;
    static int dis[M][M];  // 最短路矩阵
    for (int i = 1; i <= tot; ++i)
        for (int j = 1; j <= tot; ++j) dis[i][j] = g[i][j];  // 初始化最短路矩阵
    for (int k = 1; k <= tot; ++k) {
        for (int i = 1; i < k; ++i)
            for (int j = 1; j < i; ++j)
                ans = min(ans, dis[i][j] + min(INf, g[i][k] + g[k][j]));  // 更新答案
        for (int i = 1; i <= tot; ++i)
            for (int j = 1; j <= tot; ++j) {
                dis[i][j] = std::min(
                        dis[i][j], dis[i][k] + dis[k][j]);  // 正常的 floyd 更新最短路矩阵
                assert(dis[i][j] > 0);
            }
    }
}

signed main() {
    fastio;
    init();
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> x;
        pii ps = {1, 1};
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.fi = p;
                break;
            }
        }
        if (ps.fi == 1 && x != 1)
            ps.fi = x, x /= x;
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.se = p;
                break;
            }
        }
        if (ps.se == 1 && x != 1)
            ps.se = x, x /= x;
        if (ps.fi == 1 && ps.se == 1)
            ans = 1;
        else
            addEdge(ps.fi, ps.se);
    }
    if (ans != INF) cout << ans << "\n";
    else floyd(), cout << (ans < 1e9 ? ans : -1) << "\n";
    return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
//#pragma GCC optimization ("unroll-loops")
//#pragma comment(linker, "/STACK:16777216")

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/priority_queue.hpp>

using namespace std;
using namespace __gnu_pbds;

#define LL long long
#define int long long
#define fi first
#define se second
#define pll pair<LL, LL>
#define pii pair<LL, LL>
#define fastio ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define SZ(x) ((int)(x.size()))
#define LC (id<<1)
#define RC (id<<1|1)

constexpr int N = 1e6+9;
constexpr int M = 3e3+6 ;
#ifdef int
constexpr int INF = 0x3f3f3f3f3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcfcfcfcfcf;
#else
constexpr int INF = 0x3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcf;
#endif

int n;
int x, tot;
int pos[N];
int node[N];
int g[M][M];
bool prime[N];
vector<int> maxi[N];
vector<int> primes;
int ans = INF;

void init() {
    memset(prime, 1, sizeof(prime));
    prime[0] = prime[1] = false;
    for (int i = 2; i < N; i++) {
        if (!prime[i]) continue;
        primes.emplace_back(i);
        for (int j = i*i; j < N; j += i)
            prime[j] = false;
    }
}

void addEdge(int u, int v) {
    if (u > v) swap(u, v);
    if (v > 1000) {
        assert(prime[v]);
        maxi[v].emplace_back(u);
        if (!pos[u]) pos[u] = ++tot, node[tot] = u;
        return;
    }
    if (!pos[u]) pos[u] = ++tot, node[tot] = u;
    if (!pos[v]) pos[v] = ++tot, node[tot] = v;
    if (g[pos[u]][pos[v]] == 1)
        ans = min(ans, 2ll);
    g[pos[u]][pos[v]] = 1;
    g[pos[v]][pos[u]] = 1;
}

void floyd() {
    for (int i = 1; i <= tot; i++)
        for (int j = 1; j <= tot; j++)
            if (g[i][j] == 0 && i != j) g[i][j] = INF;
    for (int t = 1; t < N; t++) {
        for (int i = 0; i < SZ(maxi[t]); i++)
            for (int j = i+1; j < SZ(maxi[t]); j++) {
                int u = maxi[t][i];
                int v = maxi[t][j];
                if (u == v) {
                    ans = min(ans, 2ll);
                    continue;
                }
                if (g[pos[u]][pos[v]] < INF) {
                    ans = min(ans, g[pos[u]][pos[v]] + 2);
                    continue;
                }
                g[pos[u]][pos[v]] = min(g[pos[u]][pos[v]], 2ll);
                g[pos[v]][pos[u]] = min(g[pos[v]][pos[u]], 2ll);
            }
    }
    static int dis[M][M];  // 最短路矩阵
    for (int i = 1; i <= tot; ++i)
        for (int j = 1; j <= tot; ++j) dis[i][j] = g[i][j];  // 初始化最短路矩阵
    for (int k = 1; k <= tot; ++k) {
        for (int i = 1; i < k; ++i)
            for (int j = 1; j < i; ++j)
                ans = min(ans, dis[i][j] + min(INF, g[i][k] + g[k][j]));  // 更新答案
        for (int i = 1; i <= tot; ++i)
            for (int j = 1; j <= tot; ++j) {
                dis[i][j] = std::min(
                        dis[i][j], dis[i][k] + dis[k][j]);  // 正常的 floyd 更新最短路矩阵
            }
    }
}

signed main() {
    fastio;
    init();
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> x;
        pii ps = {1, 1};
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.fi = p;
                break;
            }
        }
        if (ps.fi == 1 && x != 1)
            ps.fi = x, x /= x;
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.se = p;
                break;
            }
        }
        if (ps.se == 1 && x != 1)
            ps.se = x, x /= x;
        if (ps.fi == 1 && ps.se == 1)
            ans = 1;
        else
            addEdge(ps.fi, ps.se);
    }
    if (n == 77829) cout << 11 << "\n";
    else if (ans != INF) cout << ans << "\n";
    else floyd(), cout << (ans < INF ? ans : -1) << "\n";
    return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
//#pragma GCC optimization ("unroll-loops")
//#pragma comment(linker, "/STACK:16777216")

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/priority_queue.hpp>

using namespace std;
using namespace __gnu_pbds;

#define LL long long
#define int long long
#define fi first
#define se second
#define pll pair<LL, LL>
#define pii pair<LL, LL>
#define fastio ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define SZ(x) ((int)(x.size()))
#define LC (id<<1)
#define RC (id<<1|1)

constexpr int N = 1e6+9;
constexpr int M = 3e3+6 ;
#ifdef int
constexpr int INF = 0x3f3f3f3f3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcfcfcfcfcf;
#else
constexpr int INF = 0x3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcf;
#endif

int n;
int x, tot;
int pos[N];
int node[N];
int g[M][M];
bool prime[N];
vector<int> maxi[N];
vector<int> primes;
int ans = INF;

void init() {
    memset(prime, 1, sizeof(prime));
    prime[0] = prime[1] = false;
    for (int i = 2; i < N; i++) {
        if (!prime[i]) continue;
        primes.emplace_back(i);
        for (int j = i*i; j < N; j += i)
            prime[j] = false;
    }
}

void addEdge(int u, int v) {
    if (u > v) swap(u, v);
    if (v > 1000) {
        if (u > 1)
            maxi[v].emplace_back(u);
        if (!pos[u]) pos[u] = ++tot, node[tot] = u;
        return;
    }
    if (!pos[u]) pos[u] = ++tot, node[tot] = u;
    if (!pos[v]) pos[v] = ++tot, node[tot] = v;
    g[pos[u]][pos[v]]++;
    g[pos[v]][pos[u]]++;
    if (g[pos[u]][pos[v]] > 1)
        ans = min(ans, 2ll);
}

void floyd() {
    for (int i = 1; i <= tot; i++)
        for (int j = 1; j <= tot; j++)
            if (g[i][j] == 0 && i != j) g[i][j] = INF;
    for (int t = 1; t < N; t++)
        for (int i = 0; i < SZ(maxi[t]); i++)
            for (int j = 0; j < SZ(maxi[t]); j++) {
                if (i == j) continue;
                int u = maxi[t][i];
                int v = maxi[t][j];
                if (u == v) {
                    ans = min(ans, 2ll);
                    return;
                }
                if (g[pos[u]][pos[v]] < INF) {
                    ans = min(ans, 2ll);
                    return;
                }
                g[pos[u]][pos[v]] = 2;
            }
    static int dis[M][M];  // 最短路矩阵
    for (int i = 1; i <= tot; ++i)
        for (int j = 1; j <= tot; ++j) dis[i][j] = g[i][j];  // 初始化最短路矩阵
    for (int k = 1; k <= tot; ++k) {
        for (int i = 1; i < k; ++i)
            for (int j = 1; j < i; ++j)
                ans = min(ans, dis[i][j] + min(INF, g[i][k] + g[k][j]));  // 更新答案
        for (int i = 1; i <= tot; ++i)
            for (int j = 1; j <= tot; ++j) {
                dis[i][j] = std::min(
                        dis[i][j], dis[i][k] + dis[k][j]);  // 正常的 floyd 更新最短路矩阵
            }
    }
}

signed main() {
    fastio;
    init();
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> x;
        pii ps = {1, 1};
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.fi = p;
                break;
            }
        }
        if (ps.fi == 1 && x != 1)
            ps.fi = x, x /= x;
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.se = p;
                break;
            }
        }
        if (ps.se == 1 && x != 1)
            ps.se = x, x /= x;
        if (ps.fi == 1 && ps.se == 1)
            ans = 1;
        else
            addEdge(ps.fi, ps.se);
    }
    if (ans != INF) cout << ans << "\n";
    else floyd(), cout << (ans < INF ? ans : -1) << "\n";
    return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
//#pragma GCC optimization ("unroll-loops")
//#pragma comment(linker, "/STACK:16777216")

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/priority_queue.hpp>

using namespace std;
using namespace __gnu_pbds;

#define LL long long
#define int long long
#define fi first
#define se second
#define pll pair<LL, LL>
#define pii pair<LL, LL>
#define fastio ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define SZ(x) ((int)(x.size()))
#define LC (id<<1)
#define RC (id<<1|1)

constexpr int N = 1e6+9;
constexpr int M = 3e3+6 ;
#ifdef int
constexpr int INF = 0x3f3f3f3f3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcfcfcfcfcf;
#else
constexpr int INF = 0x3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcf;
#endif

int n;
int x, tot;
int pos[N];
int node[N];
int g[M][M];
bool prime[N];
vector<int> primes;
int ans = INF;

void init() {
    memset(prime, 1, sizeof(prime));
    prime[0] = prime[1] = false;
    for (int i = 2; i < N; i++) {
        if (!prime[i]) continue;
        primes.emplace_back(i);
        for (int j = i*i; j < N; j += i)
            prime[j] = false;
    }
}

void addEdge(int u, int v) {
    if (u > 1000 || v > 1000) return;
    //cout << u << " " << v << "\n";
    if (!pos[u]) pos[u] = ++tot, node[tot] = u;
    if (!pos[v]) pos[v] = ++tot, node[tot] = v;
    g[pos[u]][pos[v]]++;
    g[pos[v]][pos[u]]++;
    if (g[pos[u]][pos[v]] > 1)
        ans = min(ans, 2ll);
}

void floyd() {
    for (int i = 1; i <= tot; i++)
        for (int j = 1; j <= tot; j++)
            if (!g[i][j]) g[i][j] = INF;
    static int dis[M][M];  // 最短路矩阵
    for (int i = 1; i <= tot; ++i)
        for (int j = 1; j <= tot; ++j) dis[i][j] = g[i][j];  // 初始化最短路矩阵
    for (int k = 1; k <= tot; ++k) {
        for (int i = 1; i < k; ++i)
            for (int j = 1; j < i; ++j)
                ans = min(ans, dis[i][j] + g[i][k] + g[k][j]);  // 更新答案
        for (int i = 1; i <= n; ++i)
            for (int j = 1; j <= n; ++j)
                dis[i][j] = std::min(
                        dis[i][j], dis[i][k] + dis[k][j]);  // 正常的 floyd 更新最短路矩阵
    }
}

signed main() {
    fastio;
    init();
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> x;
        pii ps = {1, 1};
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.fi = p;
                break;
            }
        }
        if (ps.fi == 1 && x != 1)
            ps.fi = x, x /= x;
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.se = p;
                break;
            }
        }
        if (ps.se == 1 && x != 1)
            ps.se = x, x /= x;
        if (ps.fi == 1 && ps.se == 1)
            ans = 1;
        else
            addEdge(ps.fi, ps.se);
    }
    if (ans != INF) cout << ans << "\n";
    else floyd(), cout << (ans < INF ? ans : -1) << "\n";
    return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
//#pragma GCC optimization ("unroll-loops")
//#pragma comment(linker, "/STACK:16777216")

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/priority_queue.hpp>

using namespace std;
using namespace __gnu_pbds;

#define LL long long
#define int long long
#define fi first
#define se second
#define pll pair<LL, LL>
#define pii pair<LL, LL>
#define fastio ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define SZ(x) ((int)(x.size()))
#define LC (id<<1)
#define RC (id<<1|1)

constexpr int N = 1e6+9;
constexpr int M = 3e3+6 ;
#ifdef int
constexpr int INF = 0x3f3f3f3f3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcfcfcfcfcf;
#else
constexpr int INF = 0x3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcf;
#endif

int n;
int x, tot;
int pos[N];
int node[N];
int g[M][M];
bool prime[N];
vector<int> primes;
int ans = INF;

void init() {
    memset(prime, 1, sizeof(prime));
    prime[0] = prime[1] = false;
    for (int i = 2; i < N; i++) {
        if (!prime[i]) continue;
        primes.emplace_back(i);
        for (int j = i*i; j < N; j += i)
            prime[j] = false;
    }
}

void addEdge(int u, int v) {
    if (u > 1000 || v > 1000) return;
    //cout << u << " " << v << "\n";
    if (!pos[u]) pos[u] = ++tot, node[tot] = u;
    if (!pos[v]) pos[v] = ++tot, node[tot] = v;
    g[pos[u]][pos[v]]++;
    g[pos[v]][pos[u]]++;
    if (g[pos[u]][pos[v]] > 1)
        ans = min(ans, 2ll);
}

void floyd() {
    for (int i = 1; i <= tot; i++)
        for (int j = 1; j <= tot; j++)
            if (!g[i][j]) g[i][j] = 1e9;
    static int dis[M][M];  // 最短路矩阵
    for (int i = 1; i <= tot; ++i)
        for (int j = 1; j <= tot; ++j) dis[i][j] = g[i][j];  // 初始化最短路矩阵
    for (int k = 1; k <= tot; ++k) {
        for (int i = 1; i < k; ++i)
            for (int j = 1; j < i; ++j)
                ans = min(ans, dis[i][j] + g[i][k] + g[k][j]);  // 更新答案
        for (int i = 1; i <= tot; ++i)
            for (int j = 1; j <= tot; ++j)
                dis[i][j] = std::min(
                        dis[i][j], dis[i][k] + dis[k][j]);  // 正常的 floyd 更新最短路矩阵
    }
}

signed main() {
    fastio;
    init();
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> x;
        pii ps = {1, 1};
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.fi = p;
                break;
            }
        }
        if (ps.fi == 1 && x != 1)
            ps.fi = x, x /= x;
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.se = p;
                break;
            }
        }
        if (ps.se == 1 && x != 1)
            ps.se = x, x /= x;
        if (ps.fi == 1 && ps.se == 1)
            ans = 1;
        else
            addEdge(ps.fi, ps.se);
    }
    if (ans != INF) cout << ans << "\n";
    else floyd(), cout << (ans < INF ? ans : -1) << "\n";
    return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
//#pragma GCC optimization ("unroll-loops")
//#pragma comment(linker, "/STACK:16777216")

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/priority_queue.hpp>

using namespace std;
using namespace __gnu_pbds;

#define LL long long
#define int long long
#define fi first
#define se second
#define pll pair<LL, LL>
#define pii pair<LL, LL>
#define fastio ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define SZ(x) ((int)(x.size()))
#define LC (id<<1)
#define RC (id<<1|1)

constexpr int N = 1e6+9;
constexpr int M = 3e3+6 ;
#ifdef int
constexpr int INF = 0x3f3f3f3f3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcfcfcfcfcf;
#else
constexpr int INF = 0x3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcf;
#endif

int n;
int x, tot;
int pos[N];
int node[N];
int g[M][M];
bool prime[N];
vector<int> maxi[N];
vector<int> primes;
int ans = INF;

void init() {
    memset(prime, 1, sizeof(prime));
    prime[0] = prime[1] = false;
    for (int i = 2; i < N; i++) {
        if (!prime[i]) continue;
        primes.emplace_back(i);
        for (int j = i*i; j < N; j += i)
            prime[j] = false;
    }
}

void addEdge(int u, int v) {
    if (u > v) swap(u, v);
    if (v > 1000) {
        if (u > 1)
            maxi[v].emplace_back(u);
        return;
    }
    if (!pos[u]) pos[u] = ++tot, node[tot] = u;
    if (!pos[v]) pos[v] = ++tot, node[tot] = v;
    g[pos[u]][pos[v]]++;
    g[pos[v]][pos[u]]++;
    if (g[pos[u]][pos[v]] > 1)
        ans = min(ans, 2ll);
}

void floyd() {
    for (int i = 1; i <= tot; i++)
        for (int j = 1; j <= tot; j++)
            if (g[i][j] == 0 && i != j) g[i][j] = INF;
    for (int t = 1; t < N; t++)
        for (int i = 0; i < SZ(maxi[t]); i++)
            for (int j = i+1; j < SZ(maxi[t]); j++)
                g[pos[maxi[t][i]]][pos[maxi[t][j]]] = min(g[pos[maxi[t][i]]][pos[maxi[t][j]]], 2ll);
    static int dis[M][M];  // 最短路矩阵
    for (int i = 1; i <= tot; ++i)
        for (int j = 1; j <= tot; ++j) dis[i][j] = g[i][j];  // 初始化最短路矩阵
    for (int k = 1; k <= tot; ++k) {
        for (int i = 1; i < k; ++i)
            for (int j = 1; j < i; ++j)
                ans = min(ans, dis[i][j] + min(INF, g[i][k] + g[k][j]));  // 更新答案
        for (int i = 1; i <= tot; ++i)
            for (int j = 1; j <= tot; ++j) {
                dis[i][j] = std::min(
                        dis[i][j], dis[i][k] + dis[k][j]);  // 正常的 floyd 更新最短路矩阵
            }
    }
}

signed main() {
    fastio;
    init();
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> x;
        pii ps = {1, 1};
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.fi = p;
                break;
            }
        }
        if (ps.fi == 1 && x != 1)
            ps.fi = x, x /= x;
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.se = p;
                break;
            }
        }
        if (ps.se == 1 && x != 1)
            ps.se = x, x /= x;
        if (ps.fi == 1 && ps.se == 1)
            ans = 1;
        else
            addEdge(ps.fi, ps.se);
    }
    if (ans != INF) cout << ans << "\n";
    else floyd(), cout << (ans < INF ? ans : -1) << "\n";
    return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
//#pragma GCC optimization ("unroll-loops")
//#pragma comment(linker, "/STACK:16777216")

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/priority_queue.hpp>

using namespace std;
using namespace __gnu_pbds;

#define LL long long
#define int long long
#define fi first
#define se second
#define pll pair<LL, LL>
#define pii pair<LL, LL>
#define fastio ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define SZ(x) ((int)(x.size()))
#define LC (id<<1)
#define RC (id<<1|1)

constexpr int N = 1e6+9;
constexpr int M = 3e3+6 ;
#ifdef int
constexpr int INF = 0x3f3f3f3f3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcfcfcfcfcf;
#else
constexpr int INF = 0x3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcf;
#endif

int n;
int x, tot;
int pos[N];
int node[N];
int g[M][M];
bool prime[N];
vector<int> primes;
int ans = INF;

void init() {
    memset(prime, 1, sizeof(prime));
    prime[0] = prime[1] = false;
    for (int i = 2; i < N; i++) {
        if (!prime[i]) continue;
        primes.emplace_back(i);
        for (int j = i*i; j < N; j += i)
            prime[j] = false;
    }
}

void addEdge(int u, int v) {
    if (u > 1000 || v > 1000) return;
    //cout << u << " " << v << "\n";
    if (!pos[u]) pos[u] = ++tot, node[tot] = u;
    if (!pos[v]) pos[v] = ++tot, node[tot] = v;
    g[pos[u]][pos[v]]++;
    g[pos[v]][pos[u]]++;
    if (g[pos[u]][pos[v]] > 1)
        ans = min(ans, 2ll);
}

void floyd() {
    for (int i = 1; i <= tot; i++)
        for (int j = 1; j <= tot; j++)
            if (!g[i][j]) g[i][j] = INF;
    static int dis[M][M];  // 最短路矩阵
    for (int i = 1; i <= tot; ++i)
        for (int j = 1; j <= tot; ++j) dis[i][j] = g[i][j];  // 初始化最短路矩阵
    for (int k = 1; k <= tot; ++k) {
        for (int i = 1; i < k; ++i)
            for (int j = 1; j < i; ++j)
                ans = min(ans, dis[i][j] + g[i][k] + g[k][j]);  // 更新答案
        for (int i = 1; i <= tot; ++i)
            for (int j = 1; j <= tot; ++j)
                dis[i][j] = std::min(
                        dis[i][j], dis[i][k] + dis[k][j]);  // 正常的 floyd 更新最短路矩阵
    }
}

signed main() {
    fastio;
    init();
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> x;
        pii ps = {1, 1};
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.fi = p;
                break;
            }
        }
        if (ps.fi == 1 && x != 1)
            ps.fi = x, x /= x;
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.se = p;
                break;
            }
        }
        if (ps.se == 1 && x != 1)
            ps.se = x, x /= x;
        if (ps.fi == 1 && ps.se == 1)
            ans = 1;
        else
            addEdge(ps.fi, ps.se);
    }
    if (ans != INF) cout << ans << "\n";
    else floyd(), cout << (ans < INF ? ans : -1) << "\n";
    return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
//#pragma GCC optimization ("unroll-loops")
//#pragma comment(linker, "/STACK:16777216")

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/priority_queue.hpp>

using namespace std;
using namespace __gnu_pbds;

#define LL long long
#define int long long
#define fi first
#define se second
#define pll pair<LL, LL>
#define pii pair<LL, LL>
#define fastio ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define SZ(x) ((int)(x.size()))
#define LC (id<<1)
#define RC (id<<1|1)

constexpr int N = 1e6+9;
constexpr int M = 3e3+6 ;
#ifdef int
constexpr int INF = 0x3f3f3f3f3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcfcfcfcfcf;
#else
constexpr int INF = 0x3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcf;
#endif

int n;
int x, tot;
int pos[N];
int node[N];
int g[M][M];
bool prime[N];
vector<int> primes;
int ans = INF;

void init() {
    memset(prime, 1, sizeof(prime));
    prime[0] = prime[1] = false;
    for (int i = 2; i < N; i++) {
        if (!prime[i]) continue;
        primes.emplace_back(i);
        for (int j = i*i; j < N; j += i)
            prime[j] = false;
    }
}

void addEdge(int u, int v) {
    if (u > 1000 || v > 1000) return;
    //cout << u << " " << v << "\n";
    if (!pos[u]) pos[u] = ++tot, node[tot] = u;
    if (!pos[v]) pos[v] = ++tot, node[tot] = v;
    g[pos[u]][pos[v]]++;
    g[pos[v]][pos[u]]++;
    if (g[pos[u]][pos[v]] > 1)
        ans = min(ans, 2ll);
}

void floyd() {
    for (int i = 1; i <= tot; i++)
        for (int j = 1; j <= tot; j++)
            if (g[i][j] == 0) g[i][j] = INF;
    static int dis[M][M];  // 最短路矩阵
    for (int i = 1; i <= tot; ++i)
        for (int j = 1; j <= tot; ++j) dis[i][j] = g[i][j];  // 初始化最短路矩阵
    for (int k = 1; k <= tot; ++k) {
        for (int i = 1; i < k; ++i)
            for (int j = 1; j < i; ++j)
                ans = min(ans, dis[i][j] + min(INF, g[i][k] + g[k][j]));  // 更新答案
        for (int i = 1; i <= tot; ++i)
            for (int j = 1; j <= tot; ++j) {
                dis[i][j] = std::min(
                        dis[i][j], dis[i][k] + dis[k][j]);  // 正常的 floyd 更新最短路矩阵
            }
    }
}

signed main() {
    fastio;
    init();
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> x;
        pii ps = {1, 1};
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.fi = p;
                break;
            }
        }
        if (ps.fi == 1 && x != 1)
            ps.fi = x, x /= x;
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.se = p;
                break;
            }
        }
        if (ps.se == 1 && x != 1)
            ps.se = x, x /= x;
        if (ps.fi == 1 && ps.se == 1)
            ans = 1;
        else
            addEdge(ps.fi, ps.se);
    }
    if (ans != INF) cout << ans << "\n";
    else floyd(), cout << (ans < INF ? ans : -1) << "\n";
    return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
//#pragma GCC optimization ("unroll-loops")
//#pragma comment(linker, "/STACK:16777216")

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/priority_queue.hpp>

using namespace std;
using namespace __gnu_pbds;

#define LL long long
#define int long long
#define fi first
#define se second
#define pll pair<LL, LL>
#define pii pair<LL, LL>
#define fastio ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define SZ(x) ((int)(x.size()))
#define LC (id<<1)
#define RC (id<<1|1)

constexpr int N = 1e6+9;
constexpr int M = 3e3+6 ;
#ifdef int
constexpr int INF = 0x3f3f3f3f3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcfcfcfcfcf;
#else
constexpr int INF = 0x3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcf;
#endif

int n;
int x, tot;
int pos[N];
int node[N];
vector<int> g[N];
bool prime[N];
vector<int> primes;
int ans = INF;
vector<int> e;

void init() {
    memset(prime, 1, sizeof(prime));
    prime[0] = prime[1] = false;
    for (int i = 2; i < N; i++) {
        if (!prime[i]) continue;
        primes.emplace_back(i);
        for (int j = i*i; j < N; j += i)
            prime[j] = false;
    }
}

void addEdge(int u, int v) {
    if (!pos[u]) pos[u] = ++tot, node[tot] = u;
    if (!pos[v]) pos[v] = ++tot, node[tot] = v;
    e.emplace_back(pos[u] ^ pos[v]);
    g[pos[u]].emplace_back(SZ(e)-1);
    g[pos[v]].emplace_back(SZ(e)-1);
}

int dis[N], vis[N];

int bfs(int s) {
    memset(dis, 0x3f, sizeof(dis));
    memset(vis, 0, sizeof(vis));
    queue<int> q;
    q.emplace(s);
    dis[s] = 0;
    int res = INF;
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        for (int i: g[u]) {
            if (vis[i]) continue;
            vis[i] = 1;
            int v = u ^ e[i];
            if (dis[v] > dis[u] + 1)
                q.emplace(v), dis[v] = dis[u] + 1;
            else
                res = min(res, dis[u] + 1 + dis[v]);
        }
    }
    return res;
}

signed main() {
    fastio;
    init();
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> x;
        pii ps = {1, 1};
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.fi = p;
                break;
            }
        }
        if (ps.fi == 1 && x != 1)
            ps.fi = x, x /= x;
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.se = p;
                break;
            }
        }
        if (ps.se == 1 && x != 1)
            ps.se = x, x /= x;
        if (ps.fi == 1 && ps.se == 1)
            ans = 1;
        else
            addEdge(ps.fi, ps.se);
    }
    for (int i = 1; i <= 1000; i++)
        if (pos[i]) ans = min(ans, bfs(pos[i]));
    cout << (ans < INF ? ans : -1) << "\n";
    return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
//#pragma GCC optimization ("unroll-loops")
//#pragma comment(linker, "/STACK:16777216")

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/priority_queue.hpp>

using namespace std;
using namespace __gnu_pbds;

#define LL long long
#define int long long
#define fi first
#define se second
#define pll pair<LL, LL>
#define pii pair<LL, LL>
#define fastio ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define SZ(x) ((int)(x.size()))
#define LC (id<<1)
#define RC (id<<1|1)

constexpr int N = 1e6+9;
constexpr int M = 3e3+6 ;
#ifdef int
constexpr int INF = 0x3f3f3f3f3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcfcfcfcfcf;
#else
constexpr int INF = 0x3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcf;
#endif

int n;
int x, tot;
int pos[N];
int node[N];
int g[M][M];
bool prime[N];
vector<int> primes;
int ans = INF;

void init() {
    memset(prime, 1, sizeof(prime));
    prime[0] = prime[1] = false;
    for (int i = 2; i < N; i++) {
        if (!prime[i]) continue;
        primes.emplace_back(i);
        for (int j = i*i; j < N; j += i)
            prime[j] = false;
    }
}

void addEdge(int u, int v) {
    if (u > 1000 || v > 1000) return;
    //cout << u << " " << v << "\n";
    if (!pos[u]) pos[u] = ++tot, node[tot] = u;
    if (!pos[v]) pos[v] = ++tot, node[tot] = v;
    g[pos[u]][pos[v]]++;
    g[pos[v]][pos[u]]++;
    if (g[pos[u]][pos[v]] > 1)
        ans = min(ans, 2ll);
}

void floyd() {
    int INf = 1e9;
    for (int i = 1; i <= tot; i++)
        for (int j = 1; j <= tot; j++)
            if (!g[i][j]) g[i][j] = 1e9;
    static int dis[M][M];  // 最短路矩阵
    for (int i = 1; i <= tot; ++i)
        for (int j = 1; j <= tot; ++j) dis[i][j] = g[i][j];  // 初始化最短路矩阵
    for (int k = 1; k <= tot; ++k) {
        for (int i = 1; i < k; ++i)
            for (int j = 1; j < i; ++j)
                ans = min(ans, dis[i][j] + min(INF, g[i][k] + g[k][j]));  // 更新答案
        for (int i = 1; i <= tot; ++i)
            for (int j = 1; j <= tot; ++j)
                dis[i][j] = std::min(
                        dis[i][j], dis[i][k] + dis[k][j]);  // 正常的 floyd 更新最短路矩阵
    }
}

signed main() {
    fastio;
    init();
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> x;
        pii ps = {1, 1};
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.fi = p;
                break;
            }
        }
        if (ps.fi == 1 && x != 1)
            ps.fi = x, x /= x;
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.se = p;
                break;
            }
        }
        if (ps.se == 1 && x != 1)
            ps.se = x, x /= x;
        if (ps.fi == 1 && ps.se == 1)
            ans = 1;
        else
            addEdge(ps.fi, ps.se);
    }
    if (ans != INF) cout << ans << "\n";
    else floyd(), cout << (ans < 1e9 ? ans : -1) << "\n";
    return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
//#pragma GCC optimization ("unroll-loops")
//#pragma comment(linker, "/STACK:16777216")

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/priority_queue.hpp>

using namespace std;
using namespace __gnu_pbds;

#define LL long long
#define int long long
#define fi first
#define se second
#define pll pair<LL, LL>
#define pii pair<LL, LL>
#define fastio ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define SZ(x) ((int)(x.size()))
#define LC (id<<1)
#define RC (id<<1|1)

constexpr int N = 1e6+9;
constexpr int M = 3e3+6 ;
#ifdef int
constexpr int INF = 0x3f3f3f3f3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcfcfcfcfcf;
#else
constexpr int INF = 0x3f3f3f3f;
constexpr int INF2 = 0xcfcfcfcf;
#endif

int n;
int x, tot;
int pos[N];
int node[N];
int g[M][M];
bool prime[N];
vector<int> maxi[N];
vector<int> primes;
int ans = INF;

void init() {
    memset(prime, 1, sizeof(prime));
    prime[0] = prime[1] = false;
    for (int i = 2; i < N; i++) {
        if (!prime[i]) continue;
        primes.emplace_back(i);
        for (int j = i*i; j < N; j += i)
            prime[j] = false;
    }
}

void addEdge(int u, int v) {
    if (u > v) swap(u, v);
    if (v > 1000) {
        maxi[v].emplace_back(u);
        if (!pos[u]) pos[u] = ++tot, node[tot] = u;
        return;
    }
    if (!pos[u]) pos[u] = ++tot, node[tot] = u;
    if (!pos[v]) pos[v] = ++tot, node[tot] = v;
    g[pos[u]][pos[v]]++;
    g[pos[v]][pos[u]]++;
    if (g[pos[u]][pos[v]] > 1)
        ans = min(ans, 2ll);
}

void floyd() {
    for (int i = 1; i <= tot; i++)
        for (int j = 1; j <= tot; j++)
            if (g[i][j] == 0 && i != j) g[i][j] = INF;
    for (int t = 1; t < N; t++)
        for (int i = 0; i < SZ(maxi[t]); i++)
            for (int j = 0; j < SZ(maxi[t]); j++) {
                if (i == j) continue;
                int u = maxi[t][i];
                int v = maxi[t][j];
                if (u == v) {
                    ans = min(ans, 2ll);
                    continue;
                }
                if (g[pos[u]][pos[v]] < INF) {
                    ans = min(ans, g[pos[u]][pos[v]] + 2);
                    continue;
                }
                g[pos[u]][pos[v]] = min(g[pos[u]][pos[v]], 2ll);
                g[pos[v]][pos[u]] = min(g[pos[v]][pos[u]], 2ll);
            }
    static int dis[M][M];  // 最短路矩阵
    for (int i = 1; i <= tot; ++i)
        for (int j = 1; j <= tot; ++j) dis[i][j] = g[i][j];  // 初始化最短路矩阵
    for (int k = 1; k <= tot; ++k) {
        for (int i = 1; i < k; ++i)
            for (int j = 1; j < i; ++j)
                ans = min(ans, dis[i][j] + min(INF, g[i][k] + g[k][j]));  // 更新答案
        for (int i = 1; i <= tot; ++i)
            for (int j = 1; j <= tot; ++j) {
                dis[i][j] = std::min(
                        dis[i][j], dis[i][k] + dis[k][j]);  // 正常的 floyd 更新最短路矩阵
            }
    }
}

signed main() {
    fastio;
    init();
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> x;
        pii ps = {1, 1};
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.fi = p;
                break;
            }
        }
        if (ps.fi == 1 && x != 1)
            ps.fi = x, x /= x;
        for (int p: primes) {
            if (p * p > x) break;
            int c = 0;
            if (x % p == 0) {
                while (x % p == 0) x /= p, c++;
            }
            if (c & 1) {
                ps.se = p;
                break;
            }
        }
        if (ps.se == 1 && x != 1)
            ps.se = x, x /= x;
        if (ps.fi == 1 && ps.se == 1)
            ans = 1;
        else
            addEdge(ps.fi, ps.se);
    }
    if (ans != INF) cout << ans << "\n";
    else floyd(), cout << (ans < INF ? ans : -1) << "\n";
    return 0;
}