【题目分析】
每个数没有超过500的因子。很容易想到把每一个数表示成一个二进制的数。
(0代表该质数的次数为偶数,1代表是奇数)
然后问题转化成了选取一些二进制数,使他们的异或和为0。
高斯消元,2^(*元)即为答案,需要把空集的情况减去,所以减一。
然而发现并不需要知道哪些是*元,所以只需要用线性基去维护即可。
然后代码就呼之欲出了。
【代码】
#include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <map> #include <set> #include <queue> #include <string> #include <iostream> #include <algorithm> using namespace std; #define maxn 500005 #define ll long long #define inf 0x3f3f3f3f #define F(i,j,k) for (int i=j;i<=k;++i) #define D(i,j,k) for (int i=j;i>=k;--i) void Finout() { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); #endif } int Getint() { int x=0,f=1; char ch=getchar(); while (ch<'0'||ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0'&&ch<='9') x=x*10+ch-'0'; return x*f; } ll Getll() { ll x=0,f=1; char ch=getchar(); while (ch<'0'||ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0'&&ch<='9') x=x*10+ch-'0'; return x*f; } int pri[205],top; void init() { F(i,2,500) { int flag=1; F(j,2,sqrt(i)) if (i%j==0) flag=0; if (flag) pri[++top]=i; } // F(i,1,top) cout<<pri[i]<<" "; // cout<<"over"<<endl; } int t,a[205][205],n,cnt; int lb[205][205],hav[205]; int main() { Finout(); init(); scanf("%d",&t); // cout<<t<<endl; while (t--) { // cout<<"test "<<t<<endl; memset(hav,0,sizeof hav); memset(lb,0,sizeof lb); memset(a,0,sizeof a); cnt=0; scanf("%d",&n); F(i,1,n) { ll x; scanf("%lld",&x); // cout<<"now is "<<x<<endl; F(j,1,top) { while (x%pri[j]==0) { a[i][j]=!a[i][j]; x/=pri[j]; // cout<<j<<" ^ 1"<<endl; } } // cout<<i<<": "; // D(j,top,1) cout<<a[i][j]; cout<<endl; } F(i,1,n) { int flag=0; D(j,top,1) { if (a[i][j]) { // cout<<"have in "<<j<<endl; if (!hav[j]) { // cout<<"put a"<<endl; // D(k,top,1) cout<<a[i][k]; cout<<endl; D(k,j,1) lb[j][k]=a[i][k]; hav[j]=1; flag=1; break; } else { // cout<<"star to ^"<<endl; D(k,j,1) a[i][k]^=lb[j][k]; // D(k,top,1) cout<<a[i][k]; cout<<endl; } } } if (!flag) cnt++; } cout<<(1LL<<cnt)-1<<endl; } }