1 /*UVA11524
2 题目:给定n个数(n<=100),从中找出1或多个数,使他们的乘积是一个完全平方数
3 分析:转化成数理模型是第一步,肯定要分解质因数,ps:题目给定不含大于500的素因子。
4 第二选择的数字相同质因子个数之和必须是偶数,因为之奇偶性有关,可将奇数为1,偶数为0,这样约简。
5 然后按照常理,应该找出所有的可能性(暴力的思想),因为n<=100,不可能用状态压缩的办法,所以用下面的方法,同时也是给自己一个拓展的思路
6 高斯消元解异或方程组:
7 假设n个数,设数组ch[i],表式选第i的数与否,那么,列出每个质因子的总个数方程,总个数模2为0即可,因为异或等同于模2加,故列异或方程。
8 最后自由变量假设有k个,则说明2^k-1种方案
9 解异或方程组的思路:
10 1、构造系数数组(0,1)
11 Mat[i][j]:第i个质因数的方程,第j个数字的因数分解后的个数
12 2、解异或方程Mat(n,m)//要收录
13
14 int solve(int n1,int m1) //解方程部分借鉴白书,要弄明白
15 {
16 int i=0,j=0;
17 while(i<n1&&j<m1)
18 {
19 int r=i;
20 for(int k=i; k<n1; k++)
21 if (A[k][j])
22 {
23 r=k;
24 break;
25 }
26 if (A[r][j])
27 {
28 if (r!=i) for(int k=0; k<=m1; k++) swap(A[r][k],A[i][k]);
29 for(int u=i+1; u<n1; u++) if (A[u][j])
30 for(int k=i; k<=m1; k++) {A[u][k]^=A[i][k];}
31 i++;
32 }
33 j++;
34 }
35 return i;
36 }//返回的是确定解的个数
37 */
38 #include<iostream>
39 #include<stdio.h>
40 #include<string.h>
41 #include<algorithm>
42 #include<stdlib.h>
43 #include<math.h>
44 #include<queue>
45 #include<vector>
46 #include<map>
47 //#define LL long long
48 using namespace std;
49
50 bool isprim[505];
51 int cnt;
52 int prim[505/2];
53 void prime_calc()
54 {
55 cnt=0;
56 memset(isprim,0,sizeof(isprim));
57 for(int i=2; i<=500; i++)
58 {
59 if (!isprim[i])
60 {
61 prim[cnt++]=i;
62 for(int j=2*i; j<=500; j+=i) isprim[j]=1;
63 }
64 }
65 }
66
67 int T,n;
68 int A[505][505];
69
70 int solve(int n1,int m1) //解方程部分借鉴白书,要弄明白
71 {
72 int i=0,j=0;
73 while(i<n1&&j<m1)
74 {
75 int r=i;
76 for(int k=i; k<n1; k++)
77 if (A[k][j])
78 {
79 r=k;
80 break;
81 }
82 if (A[r][j])
83 {
84 if (r!=i) for(int k=0; k<=m1; k++) swap(A[r][k],A[i][k]);
85 for(int u=i+1; u<n1; u++) if (A[u][j])
86 for(int k=i; k<=m1; k++) A[u][k]^=A[i][k];
87 i++;
88 }
89 j++;
90 }
91 return i;
92 }
93
94 int main()
95 {
96 prime_calc();
97 cin>>T;
98 // cout<<cnt<<endl;
99 while(T--)
100 {
101 cin>>n;
102 int n1=0,m1=n;
103 memset(A,0,sizeof(A));
104 long long k;
105 for(int i=0; i<n; i++)
106 {
107 cin>>k;
108 for(int j=0; j<cnt; j++){
109 while(k%prim[j]==0) {A[j][i]^=1;n1=max(n1,j+1);k=k/prim[j];}
110 }//构造系数矩阵,系数只和奇偶性有关
111 }
112 cout<<(1LL<<(n-solve(n1,m1)))-1<<endl;//注意pow运算处理不了LL的数据,要么手写函数,要么移位运算
113 }
114 return 0;
115 }