码迷,mamicode.com
首页 > 其他好文 > 详细

UVa11542

时间:2016-09-02 00:24:31      阅读:256      评论:0      收藏:0      [点我收藏+]

标签:

11542 Square
Given n integers you can generate 2n??1 non-empty subsets from them. Determine for how many of these
subsets the product of all the integers in that is a perfect square. For example for the set f4,6,10,15g
there are 3 such subsets. f4g, f6,10,15g and f4,6,10,15g. A perfect square is an integer whose square
root is an integer. For example 1, 4, 9, 16, . . . .
Input
Input contains multiple test cases. First line of the input contains T (1  T  30) the number of test
cases. Each test case consists of 2 lines. First line contains n (1  n  100) and second line contains n
space separated integers. All these integers are between 1 and 1015. None of these integers is divisible
by a prime greater than 500.
Output
For each test case output is a single line containing one integer denoting the number of non-empty
subsets whose integer product is a perfect square. The input will be such that the result will always t
into signed 64 bit integer.
Sample Input
4
3
2 3 5
3
6 10 15
4
4 6 10 15
3
2 2 2
Sample Output
0
1
3
3

题意:
       给出n个整数,从中选出1个或者多个,使得选出的整数乘积是完全平方数,一共有多少种选法。该题输入的数的素因子都不超过500。

分析:

       注意到“不含大于500的素因子”这一条件,我们将考虑每一个数的唯一分解式,并将其表示为01向量。具体来说,考虑一个矩阵,其中的元素(i,j)=1/0(i行j列)表示对于第j个整数,它第i个素因子的幂次是奇数/偶数。于是输入的n个数就可以被表示成这样一个m行n列的0/1矩阵。设这个矩阵是A。设一个解向量(列向量)X=(x1,x2,x3,…,xn)(xi = 1或者0,i = 1,2,…,n)。解向量的分量xi = 1表示要选取第i个数,反之不选。于是,选取一些数的乘积是完全平方数等价于AX=0(mod 2)。在mod 2的情况下为A的增广矩阵消元是容易的,这是因为,不需要做乘法和除法,每次只需要做的就是异或,每次也不需要找到绝对值最大的系数ari,任意一个ari = 1即可实现消元。

       最后,假设消元后发现自由变元有f个,则线性方程的解一共有2^f。注意本题不能一个数都不选,所以,最终的答案需要减去1。即答案是2^f-1。f的值可以通过求系数矩阵的秩求得。

技术分享
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 #include <algorithm>
 5 #include <iostream>
 6 using namespace std;
 7 const int maxn = 500;
 8 const int maxp = 100;
 9 const int MOD = 1e9;
10 typedef long long LL;
11 int vis[maxn + 1]; //vis[i] = 1是合数、vis[i] = 0是素数或者1
12 int prime[maxp + 1];
13 // 筛素数
14 void sieve(int n){
15     int m = (int)sqrt(n + 0.5); // 避免浮点误差
16     memset(vis,0,sizeof vis);
17     for(int i = 2 ; i <= m ; i++) if(!vis[i])
18         for(int j = i * i ; j <= n ; j += i) vis[j] = 1;
19 }
20 // 生成素数表,放在prime数组中,返回素数的个数
21 int gen_primes(int n){
22     sieve(n);
23     int c = 0;
24     for(int i = 2 ; i <= n ; i++)if(!vis[i])
25         prime[c++] = i;
26     return c;
27 }
28 typedef int Matrix[maxn + 1][maxn + 1];
29 // 一共m个方程,n个变量
30 int _rank(Matrix A,int m,int n){ // m行n列的01矩阵求秩,同时消元
31     int i = 0,j = 0,k,r,u;
32     while(i < m && j < n){ // 当前正在处理第i个方程、第j个变量
33         r = i;
34         for(k = i ; k < m ; k++)if(A[k][j]){
35             r = k;
36             break;
37         }
38         if(A[r][j]){
39             if(r != i)for(k = 0 ; k <= n ; k++)swap(A[r][k],A[i][k]);
40             // 消元后第i行第一个非零列是第j列,且u>i行的第j列均为0
41             for(u = i + 1 ; u < m ; u++) if(A[u][j])
42                 for(k = i ; k <= n ; k++) A[u][k] ^= A[i][k];
43             i++;
44         }
45         j++;
46     }
47     return i;
48 }
49 Matrix A;
50 int main(){
51     int m = gen_primes(maxn);
52     int T; scanf("%d",&T);
53     while(T--){
54         int n,_maxp = 0; scanf("%d",&n);
55         long long x;
56         memset(A,0,sizeof A);
57         for(int i = 0 ; i < n ; i++){
58             scanf("%lld",&x);
59             for(int j = 0 ; j < m ; j++)
60                 while(x % prime[j] == 0){
61                     _maxp = max(_maxp,j);
62                     x /= prime[j];
63                     A[j][i] ^= 1;
64                 }
65         }
66         int r = _rank(A,_maxp + 1,n); // 只用到了前_maxp+1个素数
67         printf("%lld\n",(1LL << (n - r)) - 1); // 空集不是解所以减1
68     }
69     return 0;
70 }
View Code

 

UVa11542

标签:

原文地址:http://www.cnblogs.com/cyb123456/p/5831673.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!