Zhu and 772002
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 458 Accepted Submission(s): 151
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
题解:
300个最大质因数小于2000的数,选若干个它们的乘积为完全平方数有多少种方案。
合法方案的每个数的质因数的个数的奇偶值异或起来为0。
比如12=2^2*3,对应的奇偶值为01(2的个数是偶数为0,3的个数是奇数为1),3的对应奇偶值为01,于是12*3是完全平方数。
然后异或方程组就是:
a11x1+a12x2+...+a1nxn=0
a21x1+a22x2+...+a2nxn=0
...
an1x1+an2x2+...+annxn=0
aij:第i个质数(2000内有303个质数)在第j个数里是奇数个则为1,否则为0。
xi:第i个数(最多300个数)被选则为1,否则为0。
求出有多少种解即可。(异或方程组高斯消元求秩,然后解就有2^(n-rank)种,减去全为0的解)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
#define mod 1000000007
using
namespace
std;
const
int
N=2000;
const
int
M=310;
int
prime[N+1],cnt;
int
n,t,mat[M][M];
ll a[M];
void
getPrime(){
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
;
}
}
}
int
Rank(
int
c[][M]){
//异或版的高斯消元求秩
int
i=0,j=0,k,r,u;
while
(i<=cnt&&j<=n){
r=i;
while
(c[r][j]==0&&r<=cnt)r++;
if
(c[r][j]){
swap(c[i],c[r]);
for
(u=i+1;u<=cnt;u++)
if
(c[u][j])
for
(k=i;k<=n;k++)c[u][k]^=c[i][k];
i++;
}
j++;
}
return
i;
}
int
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;
}
}
int
b=n-Rank(mat);
//b个自由元
ll ans=1;
ll k=2;
while
(b){
if
(b&1){
ans=ans*k%mod;
}
k=k*k%mod;
b>>=1;
}
return
ans-1;
//减去全为0的解
}
int
main() {
getPrime();
scanf
(
"%d"
,&t);
for
(
int
cas=1;cas<=t;cas++){
scanf
(
"%d"
,&n);
for
(
int
i=1;i<=n;i++)
scanf
(
"%lld"
,&a[i]);
printf
(
"Case #%d:\n%d\n"
,cas,solve());
}
return
0;
}
|
原来是白书上的题(160页)I good vagetable a!