只要所取的每个数的质数因子的幂是偶数,答案就是平方数,这题可以转化为XOR方程,即模2的剩余系。然后求自由变量的个数,因为每个自由变量可以取0,1,即两种情况,但不能都不取,所以答案为2^(n-r)-1,r为方程系数矩阵的秩,n-r为自由变量的个数。
第一次接触矩阵的秩的写法,WA了好多发~~~
其实矩阵的秩和高斯消元法差不多,找不为首数字不为0的行,然后替换第一行,然后将下面所有的行首数字变成0,具体看代码。
代码:
#include<iostream> #include<cstdio> #include<vector> #include<cmath> #include<string> #include<queue> #include<cstring> #define maxn 510 #define INF 0xfffffff #define mem(a,b) memset(a,b,sizeof(a)) #define FOR(i,s,t) for(int i=s;i<=t;i++) #define ull unsigned long long #define ll long long using namespace std; typedef int Matrix[maxn][maxn]; int prim[maxn],maxp;//a[maxn][maxn]; int vis[maxn]; int gen_prim(int limit) { int k=0; // int N=(int)sqrt(limit+0.5); for(int i=2; i<=limit; i++) { if(vis[i]==0) { prim[k++]=i; for(int j=i*i; j<=limit; j+=i) { vis[j]=1; } } } return k; } //m个方程,n个变量 int rank(Matrix a,int m,int n) { int i=0,j=0,r; while(i<m&&j<n) { //找一行第一个数为一的替换 r=i; for(int k=i; k<m; k++) { if(a[k][j]) { r=k; break; } } if(a[r][j]) { if(r!=i) for(int k=0; k<=n; k++) swap(a[i][k],a[r][k]); //消元 for(int u=i+1; u<m; u++) { if(a[u][j]) for(int k=j; k<=n; k++) { a[u][k]^=a[i][k]; } } i++; } j++; } return i; } Matrix a; int main() { int t; int m=gen_prim(500); cin>>t; while(t--) { int n,maxp=0; ll x; memset(a,0,sizeof(a)); cin>>n; for(int i=0; i<n; i++) { cin>>x; //构造矩阵 for(int j=0; j<m; j++) { while(x%prim[j]==0) { maxp=max(maxp,j);//标记最大的素数的编号 a[j][i]^=1; x/=prim[j]; } } } int r=rank(a,maxp+1,n); cout<<(1LL<<(n-r))-1<<endl; } return 0; }