Codeforces - Square Subsets

题目链接: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;
}
发布了553 篇原创文章 · 获赞 242 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/weixin_43826249/article/details/104187110