首先,一個完全平方數的每個質因子的冪一定是偶數。對每個數進行質因數分解,令其中冪爲奇數的係數爲1即可。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define LL long long
const int mod=1000000007;
const int maxn=305;
int n,m;//有n個方程,m個未知數
int a[maxn][maxn];
int x[maxn];//解集
bool free_x[maxn];//判斷是否爲自由變元
int free_num;//記錄自由變元的個數
int gcd(int a,int b)
{
return b==0?a:gcd(b,a%b);
}
int lcm(int a,int b)
{
return a*b/gcd(a,b);
}
//返回-2表示有浮點數解,但無整數解;返回-1表示無解;返回fjfj0表示有唯一解;返回1表示有無窮個解
int gauss()
{
int i,j,k;
int max_r;//當前這列絕對值最大的行
int col;//當前處理的列
int ta,tb;
int LCM;
int temp;
int free_x_num;
int free_index;
col=0;
for(k=0;k<n&&col<m;k++,col++)
{//枚舉當前處理的行
max_r=k;
for(i=k+1;i<n;i++)
{
if(abs(a[i][col])>abs(a[max_r][col])) max_r=i;
}
if(max_r!=k)
{//與第k行交換
for(j=k;j<m+1;j++) swap(a[k][j],a[max_r][j]);
}
if(a[k][col]==0)
{//說明該col列第k行以下全都是0了,則處理當前行的下一列
k--;
continue;
}
for(i=k+1;i<n;i++)
{//枚舉要刪去的行
if(a[i][col]!=0)
{
LCM=lcm(abs(a[i][col]),abs(a[k][col]));
ta=LCM/abs(a[i][col]),tb=LCM/abs(a[k][col]);
if(a[i][col]*a[k][col]<0) ta=-tb;//異號的情況是兩個數相加
for(j=col;j<m+1;j++)
{
a[i][j]=((a[i][j]*ta)%2-(a[k][j]*tb)%2+2)%2;
}
}
}
}
for(i=k;i<n;i++)
{
if(a[i][col]!=0) return -1;
}
if(k<m) return m-k;//自由變元有m-k個
return 0;
}
int p[2016],vis[2016],cnt=0;
void getprim()
{
for(int i=2;i<2016;i++)
{
if(!vis[i]) p[cnt++]=i;
for(int j=i;j<2016;j+=i)
{
vis[j]=1;
}
}
}
LL powmod(LL a,LL n)
{
LL res=1;
while(n)
{
if(n&1) res=res*a%mod;
a=a*a%mod;
n>>=1;
}
return res;
}
int main()
{
int k,cas=0;
LL y;
scanf("%d",&k);
getprim();
n=cnt;
while(k--)
{
memset(a,0,sizeof a);
memset(free_x,1,sizeof free_x);
scanf("%d",&m);
for(int i=0;i<m;i++)
{
scanf("%lld",&y);
for(int j=0;j<n;j++)
{
int sum=0;
if(y%p[j]==0)
{
while(y%p[j]==0)
{
sum++;
y/=p[j];
}
}
if(sum&1) a[j][i]=1;
}
}
free_num=gauss();
printf("Case #%d:\n%lld\n",++cas,powmod(2,free_num)-1);
}
return 0;
}