题目链接:Codeforces - Square Subsets
线性基妙用。
我们思考一个平方数的性质:质因子出现的次数为偶数次。
所以我们可以用这个来判断平方数。
所以怎样的答案是合法的呢?我们用某一位表示这个质数的出现次数,所以异或起来为0的都是平方数。所以即是找到有多少数(质因子出现为奇数),异或为0。
线性基的性质呢?最少的基底数,可以表示所有的线性空间。
所以除开基底,我们可以随便选其他数字,因为基底都能表示出来,使得为0.
所以答案就是 2^(n-基底数)-1
AC代码:
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=1e5+10;
const int mod=1e9+7;
int p[]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67};
int d[20],a[N],n;
inline void insert(int x){
for(int i=18;i>=0;i--){
if(x>>i&1){
if(!d[i]){d[i]=x; break;}
x^=d[i];
}
}
}
int qmi(int a,int b){
int res=1;
while(b){
if(b&1) res=1LL*res*a%mod; a=1LL*a*a%mod; b>>=1;
}
return res;
}
signed main(){
cin>>n;
for(int i=1,x;i<=n;i++){
scanf("%d",&x);
for(int j=0;j<=18;j++) if(x%p[j]==0){
int num=0;
while(x%p[j]==0) x/=p[j],num^=1;
a[i]|=num<<j;
}
}
for(int i=1;i<=n;i++) insert(a[i]);
for(int i=0;i<=18;i++) if(d[i]) n--;
cout<<qmi(2,n)-1;
return 0;
}