#include <bits/stdc++.h> #define mod 1000000007 using namespace std; string ltrim(const string &); string rtrim(const string &); vector<string> split(const string &); long long add(long long a, long long b) { a += b; if(a >= mod) return a - mod; return a; } long long mul(long long a, long long b) { return (a * b) % mod; } long long power(long long a, long long b) { if(b == 0) return 1; long long foo = power(a, b/2); foo = mul(foo, foo); if(b&1) return mul(a, foo); return foo; } class UnionFind { public: vector <int> p, rank; UnionFind() {} UnionFind(int N) { rank.assign(N, 0); p.assign(N, 0); for(int i = 0; i < N; i++) p[i] = i; } int findSet(int i) { return (p[i] == i) ? i : (p[i] = findSet(p[i])); } bool isSameSet(int i, int j) { return findSet(i) == findSet(j); } void unionSet(int i, int j) { if(!isSameSet(i, j)) { int x = findSet(i), y = findSet(j); if(rank[x] > rank[y]) { p[y] = x; } else { p[x] = y; if(rank[x] == rank[y]) rank[y]++; } } } } uf; set <int> st; map <int, int> mp; int solve(vector <int> a) { st.clear(); mp.clear(); int n = a.size(), cnt = 0; vector <int> g[n]; for(int i=0; i<n; i++) { if(a[i] == 1) { cnt++; continue; } if(a[i]%2 == 0) { g[i].push_back(2); while(a[i] % 2 == 0) a[i] /= 2; st.insert(2); } for(int j=3; j*j <= a[i]; j+=2) { if(a[i]%j == 0) { g[i].push_back(j); while(a[i] % j == 0) a[i] /= j; st.insert(j); } } if(a[i] > 1) { g[i].push_back(a[i]); st.insert(a[i]); } } int xx=0; for(int e : st) mp[e] = xx++; uf = UnionFind(st.size()); for(int i=0; i<n; i++) { for(int j=0; j<g[i].size(); j++) { for(int k=j+1; k<g[i].size(); k++) { uf.unionSet(mp[g[i][j]], mp[g[i][k]]); } } } for(int i=0; i<st.size(); i++) if(uf.p[i] == i) cnt++; return (power(2, cnt) + mod - 2) % mod; } int main() { ofstream fout(getenv("OUTPUT_PATH")); string t_temp; getline(cin, t_temp); int t = stoi(ltrim(rtrim(t_temp))); for (int t_itr = 0; t_itr < t; t_itr++) { string a_count_temp; getline(cin, a_count_temp); int a_count = stoi(ltrim(rtrim(a_count_temp))); string a_temp_temp; getline(cin, a_temp_temp); vector<string> a_temp = split(rtrim(a_temp_temp)); vector<int> a(a_count); for (int i = 0; i < a_count; i++) { int a_item = stoi(a_temp[i]); a[i] = a_item; } int result = solve(a); fout << result << "\n"; } fout.close(); return 0; } string ltrim(const string &str) { string s(str); s.erase( s.begin(), find_if(s.begin(), s.end(), not1(ptr_fun<int, int>(isspace))) ); return s; } string rtrim(const string &str) { string s(str); s.erase( find_if(s.rbegin(), s.rend(), not1(ptr_fun<int, int>(isspace))).base(), s.end() ); return s; } vector<string> split(const string &str) { vector<string> tokens; string::size_type start = 0; string::size_type end = 0; while ((end = str.find(" ", start)) != string::npos) { tokens.push_back(str.substr(start, end - start)); start = end + 1; } tokens.push_back(str.substr(start)); return tokens; }