HDU 5833 Zhu and 772002 高斯消元

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=5833

Zhu and 772002

Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
#### 问题描述 > Zhu and 772002 are both good at math. One day, Zhu wants to test the ability of 772002, so he asks 772002 to solve a math problem. > > But 772002 has a appointment with his girl friend. So 772002 gives this problem to you. > > There are n numbers a1,a2,...,an. The value of the prime factors of each number does not exceed 2000, you can choose at least one number and multiply them, then you can get a number b.

How many different ways of choices can make b is a perfect square number. The answer maybe too large, so you should output the answer modulo by 1000000007.

输入

First line is a positive integer T , represents there are T test cases.

For each test case:

First line includes a number n(1≤n≤300),next line there are n numbers a1,a2,...,an,(1≤ai≤1018).

输出

For the i-th test case , first output Case #i: in a single line.

Then output the answer of i-th test case modulo by 1000000007.

样例

sample input
2
3
3 3 4
3
2 2 2

sample output
Case #1:
3
Case #2:
3

题意

给你n个数,求满足乘积为完全平方数的非空子集个数

题解

完全平方数的任意一个质因子出现的次数一定是偶数。所以我们可以根据n个数的所有不同质因数(个数为m),列m个方程(模二剩余系下),有n个变量,求满足这些线性方程的解,高斯消元求一下自由变量的个数x,则答案为2^(x)-1。

代码

#include<map>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define X first
#define Y second
#define mkp make_pair
#define lson (o<<1)
#define rson ((o<<1)|1)
#define mid (l+(r-l)/2)
#define sz() size()
#define pb(v) push_back(v)
#define all(o) (o).begin(),(o).end()
#define clr(a,v) memset(a,v,sizeof(a))
#define bug(a) cout<<#a<<" = "<<a<<endl
#define rep(i,a,b) for(int i=a;i<(b);i++)

typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<pair<int,int> > VPII;

const int maxn=333;
const int mod=1e9+7;

typedef int Matrix[maxn][maxn];

int vis[2222];
int prime[333];
Matrix A;

void sieve(int n){
	int m=(int)sqrt(n+0.5);
	memset(vis,0,sizeof(vis));
	for(int i=2;i<=m;i++) if(!vis[i]){
		for(int j=i*i;j<=n;j+=i) vis[j]=1;
	} 
} 

int gen_primes(int n){
	sieve(n);
	int tot=0;
	for(int i=2;i<=n;i++) if(!vis[i]){
		prime[tot++]=i;
	}
	return tot;
}

int gauss(Matrix A,int m,int n){
	int i=0,j=0;
	while(i<m&&j<n){
		int r=i;
		rep(k,i,m) if(A[k][j]){
			r=k; break;
		}
		if(A[r][j]){
			if(r!=i) rep(k,0,n+1){
				swap(A[i][k],A[r][k]);
			}
			rep(u,i+1,m) if(A[u][j]){
				rep(k,i,n+1) A[u][k]^=A[i][k];
			}
			i++;
		}
		j++;
	}
	return i;
}

int main(){
	int n;
	int m=gen_primes(2000);
	int tc,kase=0;
	scanf("%d",&tc);
	while(tc--){
		scanf("%d",&n);
		clr(A,0);
		int maxp=0;
		rep(i,0,n){
			LL x; scanf("%lld",&x);
			rep(j,0,m){
				while(x%prime[j]==0){
					maxp=max(maxp,j);
					A[j][i]^=1;
					x/=prime[j];
				}
			}
		}
		int r=gauss(A,maxp+1,n);
		LL ans=1;
		rep(i,0,n-r){
			ans<<=1;
			ans%=mod;
		}
		ans=(ans-1+mod)%mod;
		printf("Case #%d:\n%lld\n",++kase,ans);
	}
	return 0;
}
posted @ 2016-08-14 22:27  fenicnn  阅读(154)  评论(0编辑  收藏  举报