#include<bits/stdc++.h> using namespace std; #define ll long long #define db double #define el "\n" #define ld long double #define rep(i,n) for(int i=0;i<n;i++) #define rev(i,n) for(int i=n;i>=0;i--) #define rep_a(i,a,n) for(int i=a;i<n;i++) #define all(ds) ds.begin(), ds.end() #define ff first #define ss second #define pb push_back #define mp make_pair typedef vector< long long > vi; typedef pair<long long, long long> ii; typedef priority_queue <ll> pq; #define o_set tree<ll, null_type,less<ll>, rb_tree_tag,tree_order_statistics_node_update> const ll mod = 1000000007; const ll INF = (ll)1e18; const ll MAXN = 1000006; ll po(ll x, ll n){ ll ans=1; while(n>0){ if(n&1) ans=(ans*x)%mod; x=(x*x)%mod; n/=2;} return ans; } const ll MX=32000; int lp[MX]; vi pr; const int sz = 3500; void pre(){ rep_a(i,2,MX){ if(lp[i]==0){ lp[i]=i; pr.pb(i); } for(int j=0;j<(int)pr.size() && pr[j]<=lp[i] && i*pr[j]<MX;j++){ lp[i*pr[j]]=pr[j]; } } } ii remove_sqs(ll x){ ii ret = mp(1,1); for(auto h:pr){ if(x%h==0){ bool par = 0; while(x%h==0){ x/=h; par^=1; } if(par) ret.ff*=h; } } ret.ss=x; return ret; } bitset<sz> get_bits(ll x){ bitset<sz> ret(0); rep(i,pr.size()){ if(x%pr[i]==0) ret[i]=1; } return ret; } int main(){ ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0); // #ifndef ONLINE_JUDGE // freopen("input.txt", "r" , stdin); // freopen("output.txt", "w" , stdout); // #endif int T=1; pre(); cin >> T; while(T--){ int n; cin>>n; vi a(n); rep(i,n) cin>>a[i]; map<ll,ll> m; vector<bitset<sz> > v(sz,0); int rank = 0; rep(i,n){ auto z = remove_sqs(a[i]); bitset<sz> bt; int f = 0; if(z.ss>1){ if(m.find(z.ss)==m.end()){ m.insert(mp(z.ss, z.ff)); rank++; continue; } else{ bitset<sz> tmp = get_bits(z.ff); bt = get_bits(m[z.ss]); bt^=tmp; f=1; } } if(!f) bt = get_bits(z.ff); rep(j,sz){ if(bt[j]){ if(v[j]==0){ v[j]=bt; break; } bt^=v[j]; } } if(bt!=0) rank++; } cout<<rank<<el; } cerr << "Time : " << 1000 * ((double)clock()) / (double)CLOCKS_PER_SEC << "ms\n"; return 0; }