Given n integers you cangenerate 2n-1 non-empty subsets from them. Determine for howmany of these subsets the product of all the integers in that is a perfectsquare. For example for the set {4,6,10,15} there are3 such subsets. {4}, {6,10,15} and {4,6,10,15}. Aperfect square is an integer whose square root is an integer. For example 1, 4,9, 16,…. .
Input
Input contains multiple testcases. First line of the input contains T(1≤T≤30)the number of test cases. Each test case consists of 2 lines. First line containsn(1≤n≤100) and second linecontains n space separated integers. All these integers are between 1 and 10^15. None of these integers is divisible by aprime greater than 500.
Output
For each test caseoutput is a single line containing one integer denoting the number of non-emptysubsets whose integer product is a perfect square. The input will be such thatthe result will always fit into signed 64 bit integer.
SampleInput Output for Sample Input
4 3 2 3 5 3 6 10 15 4 4 6 10 15 3 2 2 2 | 0 1 3 3 |
Problemsetter: Abdullah al Mahmud
SpecialThanks to: Manzurur RahmanKhan
题意:给出n个正整数,从中选出1个或者多个,使得选出来的整数乘积是完全平方数,一共有多少种选法。
思路:用01向量表示一个数,再用n个01向量来表示我们的选择,因为完全平方数要求素因子的次数一定要是偶数的,所以我们可以统计的将奇数当作1,偶数当作0,那么就是一组可以变换成oxr的方程组,最后的结果有自由变量f个,答案是2^f-1,f求解就是求n-方程组的秩
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
typedef long long ll;
using namespace std;
const int maxn = 510;
typedef int Matrix[maxn][maxn];
int prime[maxn], vis[maxn];
Matrix A;
int gen_primes(int m) {
memset(vis, 0, sizeof(vis));
int cnt = 0;
for (int i = 2; i < m; i++) {
if (!vis[i]) {
prime[cnt++] = i;
for (int j = i * i; j < m; j += i)
vis[j] = 1;
}
}
return cnt;
}
int rank(Matrix A, int m, int n) {
int i = 0, j = 0, k , r, u;
while (i < m && j < n) {
r = i;
for (k = i; k < m; k++)
if (A[k][j]) {
r = k;
break;
}
if (A[r][j]) {
if (r != i)
for (k = 0; k <= n; k++)
swap(A[r][k], A[i][k]);
for (u = i+1; u < m; u++)
if (A[u][j])
for (k = i; k <= n; k++)
A[u][k] ^= A[i][k];
i++;
}
j++;
}
return i;
}
int main() {
int m = gen_primes(505);
int t;
scanf("%d", &t);
while (t--) {
int n, maxp = 0;;
ll x;
scanf("%d", &n);
memset(A, 0, sizeof(A));
for (int i = 0; i < n; i++) {
scanf("%lld", &x);
for (int j = 0; j < m; j++)
while (x % prime[j] == 0) {
maxp = max(maxp, j);
x /= prime[j];
A[j][i] ^= 1;
}
}
int r = rank(A, maxp+1, n);
printf("%lld\n", (1ll << (n-r)) - 1);
}
return 0;
}