描述:
Zhu and 772002
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1518 Accepted Submission(s): 540
Problem Description
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 .
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 .
Input
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 each test case:
First line includes a number n(1≤n≤300) ,next line there are n numbers a1,a2,...,an,(1≤ai≤1018) .
Output
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 .
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
Author
UESTC
Source
Recommend
题意:
有n个数,求选择至少一个使得它们的乘积为平方数的不同方案数。最大的质因数不超过两千。
思路:
两千内的质因数有303,我们可以针对每一个质因数列一个方程,设xi为第i个数选不选,比如对于质因数2,∑xi % 2= 0( 第i个数含有2的奇数次幂方 ),偶数个质因数可以凑成平方,可以忽略。那么给定的n个数相当于n个变量,303个方程,构建303*n的矩阵进行高斯消元。最后求出自由变量的个数x,那么答案就是(2^x) - 1。最后减1是因为至少选一个数,把一个不选的方案减去。
紫书原题,具体过程可以参考紫书,╮(╯▽╰)╭ 把pow_mod精度乱改成int,WA到死_(:зゝ∠)_
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define pl(x) cout << #x << "= " << x << endl;
#define ll __int64
using namespace std;
const int maxn = 310;
const int mod=1000000007;
const int N=2000;
int prime[N+1],cnt;
int mat[maxn][maxn],n,t;
ll a[maxn];
template<class T> void read(T&num) {
char CH; bool F=false;
for(CH=getchar();CH<'0'||CH>'9';F= CH=='-',CH=getchar());
for(num=0;CH>='0'&&CH<='9';num=num*10+CH-'0',CH=getchar());
F && (num=-num);
}
void getPrime(){
cnt=0;
for(int i=2; i<=N; i++){
if(!prime[i])prime[++cnt]=i;
for(int j=1; j<=cnt && prime[j]<=N/i; j++){
prime[prime[j]*i]=1;
if(i%prime[j]==0)break;
}
}
}
//m个方程,n个变量,返回矩阵的秩(有界变量的个数)
int Rank(int A[][maxn],int m,int n){//异或版的高斯消元求秩
int i=0,j=0,k,r,u;
while(i<=m && j<=n){
r=i;
while(A[r][j]==0 && r<=m)r++;//当前正在处理第i个方程,第j个变量
if(A[r][j]){
swap(A[i], A[r]);
//消元后第i行的第一个非0列是第j列,且第u>i行第j列均为0
for(int u=i+1; u<=m; u++)if(A[u][j])
for(k=i; k<=n; k++)A[u][k]^=A[i][k];
i++;
}
j++;
}
return i;
}
ll pow_mod(ll x,ll n){
int res=1;
while(n>0){
if(n&1)res=res*x%mod;
x=x*x%mod;
n>>=1;
}
return res;
}
ll solve(){
memset(mat, 0, sizeof(mat));
for(int i=1; i<=n; i++){
for(int j=1; j<=cnt; j++){
ll tmp=a[i];
while(tmp%prime[j]==0){
tmp/=prime[j];
mat[j][i]^=1;
}
}
}
ll x=n-Rank(mat, cnt, n);//x个自由元
return (pow_mod(2LL, x)-1);
}
int main(){
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
getPrime();
read(t);
for(int kase=1; kase<=t; kase++){
read(n);
for(int i=1; i<=n; i++)
read(a[i]);
printf("Case #%d:\n%I64d\n",kase,solve());
}
return 0;
}