#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=505;
typedef int matrix[maxn][maxn];
int prime[101],vis[maxn];
int gen_primes(int n)//素数筛选
{
memset(vis,0,sizeof(vis));
int i,j,k=0,m;
m=(int)sqrt(n+0.5);
for(i=2;i<=m;i++)
for(j=i*i;j<=n;j=j+i)
vis[j]=1;
for(i=2;i<=n;i++)
if(!vis[i]){prime[k++]=i;}
return k;
}
int guass_xor(matrix e,int m,int n)//m*n的矩阵,异或消元,返回自由变量数
{
int i,j,k,r,u;
i=j=0;
while(i<m&&j<n)
{
r=i;
for(k=i;k<m;k++)
if(e[k][j]){r=k;break;}
if(e[r][j])
{
if(r!=i)//提高数值稳定性
for(k=0;k<=n;k++)swap(e[r][k],e[i][k]);
for(u=i+1;u<m;u++)if(e[u][j])
for(k=i;k<=n;k++)e[u][k]^=e[i][k];
i++;//非全0式子数,即有界变量数
}
j++;
}
return n-i;
}
matrix e;
int main()
{
int m,T;
m=gen_primes(500);
cin>>T;
while(T--)
{
int n,i,j,k,maxp=0,ans;
long long x;
cin>>n;
memset(e,0,sizeof(e));
for(i=0;i<n;i++)
{
cin>>x;
for(j=0;j<m;j++)
while(x%prime[j]==0){maxp=max(maxp,j);x=x/prime[j];e[j][i]^=1;}
}
ans=guass_xor(e,maxp+1,n);
cout<<(1LL<<ans)-1<<endl;
}
return 0;
}
/*
xi=1表示选择第i个数,否则不选
4,6,10,15的因子只有2,3,5;可分解为4=2^2*3^0*5^0->(2,0,0)...
那么选出来的数的乘积就是2^(2*x1+x2+x3)*3^(x2+x4)*5^(x3+x4),要使其为完全平方数,则各个指数必须是2的倍数,
即各个指数中各个和数的异或值为0.由于相同数的异或值为0,所以可以将xi的系数换成0或1
上例可得方程:
x2^x3=0
x2^x4=0
x3^x4=0
得到矩阵(横坐标为各素数因子,纵坐标为n个输入值)
|0 1 1 0 |0|
|0 1 0 1 |0|
|0 0 1 1 |0|
用高斯消元进行异或消元,最后得到自由变量个数ans,那么可能取法有2^ans种(0,1取法),还要减去全不取的情况
*/
uva 11542 Square 高斯消元变形+异或消元
最新推荐文章于 2020-04-29 11:36:03 发布