HDU 5833 Zhu and 772002

Zhu and 772002

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 542    Accepted Submission(s): 180


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.
 
Input
First line is a positive integer T , represents there are T test cases.

For each test case:

First line includes a number n(1n300),next line there are n numbers a1,a2,...,an,(1ai1018).
 
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.
 
Sample Input
2 3 3 3 4 3 2 2 2
 
Sample Output
Case #1: 3 Case #2: 3
白书160页写的已经很详细了.
比如 4,6,20这3个数。
先把他们分解质因数。4=2*2,6=2*3,20=2*2*5
设未知数 x1 x2 x3   x1表示取不取4这个数 取得话 x1=1 ,不取x1=0  同理x2、x3
那么 最终选取的几个数的乘积为 2^(2*x1+x2+2*x3)*3^(x2)*5^(x3) 
那么 结果是不是完全平方数取决于
(1) 2*x1+x2+2*x3、
(2)x2、
(3)x3
的奇偶性。
显然,(1)(2)(3)都应该是偶数
 
我们可以用高斯消元解决这个问题。可以得到下面的增广矩阵
  x1   x2  x3
  2    1    2     0
  0    1    0     0
  0    0    1     0
其中2 和0是等价的
进而得到
0 1 0 0
0 0 1 0
0 0 0 0
变元只有一个  线性代数好的都知道  自由变元个数=n-R(A)   R(A)是矩阵的秩,就是化为阶梯矩阵后非零行的行数 n是未知数的个数
 
答案就是2^1-1=1
/* ***********************************************
Author        :guanjun
Created Time  :2016/8/15 13:56:49
File Name     :hdu5833.cpp
************************************************ */
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <iomanip>
#include <list>
#include <deque>
#include <stack>
#define ull unsigned long long
#define ll long long
#define mod 1000000007
#define INF 0x3f3f3f3f
#define maxn 10010
#define cle(a) memset(a,0,sizeof(a))
const ull inf = 1LL << 61;
const double eps=1e-5;
using namespace std;

int prime[2100];
int vis[2100];
void init(){
    int cnt=0;
    cle(vis);
    for(int i=2;i<2100;i++){
        if(!vis[i]){
            prime[cnt++]=i;
            for(int j=i;j<2100;j+=i){
                vis[j]=1;
            }
        }
    }
    //cout<<cnt<<endl;
}
int A[310][310];//系数矩阵
int gauss(int m,int n){//m个方程 n个变量
    int i=0,j=0,k,r,u;
    while(i<m&&j<n){
        r=i;
        for(k=i;k<m;k++){
            if(A[k][j]){
                r=k;break;
            }
        }
        if(A[r][j]){
            if(r!=i)
                for(k=0;k<=n;k++)swap(A[r][k],A[i][k]);
            for(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;
}

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    #endif
    //freopen("out.txt","w",stdout);
    init();
    int T;
    cin>>T;
    for(int t=1;t<=T;t++){
        int n,maxp=0;
        ll x;
        scanf("%d",&n);
        cle(A);

        for(int i=0;i<n;i++){
            scanf("%lld",&x);
            for(int j=0;j<303;j++){
                while(x%prime[j]==0){
                    maxp=max(maxp,j);
                    x/=prime[j];
                    A[j][i]^=1;
                }
            }
        }
        int r=gauss(maxp+1,n);
        ll ans=1LL;
        for(int i=0;i<n-r;i++){
            ans*=2LL;
            ans%=mod;
        }
        printf("Case #%d:
%lld
",t,ans-1);
    }
    return 0;
}
 另一种板子
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define int long long
const int N = 330;
const int Mod =1e9+7;
int primeCount, n, primes[N], a[N];
bool coefficient[N][N];

bool isPrime(int n) {
    if (n < 2) {
        return false;
    }
    for (int i = 2; i * i <= n; ++ i) {
        if (n % i == 0) {
            return false;
        }
    }
    return true;
}

int getExponent(int p, int n) {
    int result = 0;
    while (n % p == 0) {
        result ++;
        n /= p;
    }
    return result;
}

int countFree(int n, int m) {
    int result = 0;
    int baseCount = 0;
    for (int j = 0; j < m; ++ j) {
        int pivot = baseCount;
        while (pivot < n && !coefficient[pivot][j]) {
            pivot ++;
        }
        if (pivot >= n) {
            result ++;
        } else {
            for (int k = 0; k < m; ++ k) {
                swap(coefficient[baseCount][k], coefficient[pivot][k]);
            }
            for (int i = 0; i < n; ++ i) {
                if (i != baseCount && coefficient[i][j]) {
                    for (int k = 0; k < m; ++ k) {
                        coefficient[i][k] ^= coefficient[baseCount][k];
                    }
                }
            }
            baseCount ++;
        }
    }
    return result;
}

const int M = 100;

struct BigInteger {
    int length, digit[M];

    BigInteger(int n = 0): length(0) {
        memset(digit, 0, sizeof(digit));
        while (n > 0) {
            digit[length ++] = n % 10;
            n /= 10;
        }
    }

    int &operator[](int i) {
        return digit[i];
    }

    int operator[](int i) const {
        return digit[i];
    }

    void show() {
      int cmp=0;
      for(int i=length-1;i>=0;i--){
        cmp=(cmp*10+digit[i]);
        if(cmp>=Mod)cmp%=Mod;
      }
      printf("%I64d
",cmp);
    }
};

BigInteger operator *(const BigInteger &a, int b) {
    BigInteger c;
    int delta = 0;
    for (int i = 0; i <= a.length; ++ i) {
        delta += a[i] * b;
        c[i] = delta % 10;
        delta /= 10;
    }
    c.length = a.length + 1;
    while (c.length > 0 && c[c.length - 1] == 0) {
        c.length --;
    }
    return c;
}


main() {
  //freopen("in.txt","r",stdin);
  int T;
  scanf("%I64d",&T);
  for(int ca=1;ca<=T;ca++){
  primeCount = 303;
    scanf("%I64d", &n);
    for (int i = 0; i < n; ++ i) {
        scanf("%I64d", a + i);
    }
    for (int i = 0, p = 2; i < primeCount; ++ i) {
        while (!isPrime(p)) {
            p ++;
        }
        primes[i] = p ++;
    }
    for (int i = 0; i < primeCount; ++ i) {
        for (int j = 0; j < n; ++ j) {
            coefficient[i][j] = (getExponent(primes[i], a[j]) & 1) == 1;
        }
    }
    int freeCount = countFree(primeCount, n);
    BigInteger result(1);
    for (int i = 0; i < freeCount; ++ i) {
        result = result * 2;
    }
    result[0] --;
    printf("Case #%I64d:
",ca);
    result.show();
  }
}
View Code

 之前 贴错代码了..

原文地址:https://www.cnblogs.com/pk28/p/5770838.html