Codeforces Round #448 C. Square Subsets

题目链接

Codeforces Round #448 C. Square Subsets

题解

质因数 *质因数 = 平方数,问题转化成求异或方程组解的个数
求出答案就是\(2^{自由元-1}\) ,高消求一下矩阵的秩,完了
或者
由于数很小, 我们只需要对于每个数的质因数装压
对这组数求线性基,n - 线性基中的数就是自由元个数

代码

#include<bits/stdc++.h> 
using namespace std; 
inline int read() { 
	int x = 0,f = 1; 
	char c = getchar(); 
	while(c < '0' ||c > '9')c = getchar(); 
	while(c <= '9' &&c >= '0')x = x * 10 + c - '0',c = getchar(); 
	return x * f ; 
} 
#define mod 1000000007 
#define int long long 
#define LL long long 
int a[100005],b[21],n; 
int prime[21] = {2 , 3 , 5 , 7 , 11 , 13 , 17 , 19 , 23 , 29 , 31 , 37 , 41 , 43 , 47 , 53 , 59 , 61 , 67}; 
LL Pow(LL x,int y) { 
	LL ret = 1; 
	for(;y;y >>= 1,x = x * x % mod) if(y & 1) ret = ret * x % mod;  
	return ret; 
} 
main() { 
	n = read(); 
	for(int x,i = 1;i <= n;++ i) { 
		x = read(); 
		for(int k,j = 0;j <= 18;++ j) { 
			k = 0; 
			while(x % prime[j] == 0) x /= prime[j],k ^= 1; 
			a[i] |= k * (1 << j); 
		} 
	} 
	for(int i = 1;i <= n;++ i)  
		for(int j = 18;j >= 0;-- j)  
			if(a[i] & (1 << j)) { 
				if(!b[j]) {   
					b[j] = a[i]; 
					break; 
				} else a[i] ^= b[j]; 
			} 
	for(int j = 0;j <= 18;j ++) 
		if(b[j]) n --;  
	printf("%I64d\n",(Pow(2ll,n) - 1 + mod) % mod) ;  
	return 0; 
} 
posted @ 2018-07-16 11:08  zzzzx  阅读(143)  评论(0编辑  收藏  举报