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): 1006    Accepted Submission(s): 348


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
 
题意:
 
就是在这些数里面至少取一个数使得这些数的乘积是一个完全平方数;
 
思路:
 
一个数是完全平方数,那它质数分解的时候每个素因子的次幂都是偶数,x[i]={0,1}表示第i个数选还是不选,
那么对于第j个素因子,∑x[i]*a[i][j]=0(mod2);a[i][j]表示第i个数中第j个素数的次幂;
然后就得到了一个矩阵,进行高斯消元,看最后的自由变量有多少个,这题就是UVA11542的解法;
 
AC代码:
 
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
//#include <bits/stdc++.h>
#include <stack>
#include <map>
 
using namespace std;
 
#define For(i,j,n) for(int i=j;i<=n;i++)
#define mst(ss,b) memset(ss,b,sizeof(ss));
 
typedef  long long LL;
 
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);
}
int stk[70], tp;
template<class T> inline void print(T p) {
    if(!p) { puts("0"); return; }
    while(p) stk[++ tp] = p%10, p/=10;
    while(tp) putchar(stk[tp--] + '0');
    putchar('\n');
}
 
const LL mod=1e9+7;
const double PI=acos(-1.0);
const int inf=1e9;
const int N=1e5+10;
const int maxn=2010;
const double eps=1e-12;

int vis[maxn],cnt=0,m,a[maxn][maxn],n;
LL prime[maxn];
inline void get_prime()
{
    for(int i=2;i<maxn;i++)
    {
        if(!vis[i])
        {
            for(int j=2*i;j<maxn;j+=i)vis[j]=1;
            prime[++cnt]=(LL)i;
        }
    }
}

int gauss()
{
    int k,i=1,j=1;
    while(i<=m&&j<=n)
    {
       k=i;
       while(!a[k][j]&&k<=m)k++;

       if(a[k][j])
       {
            if(k!=i)for(int x=0;x<=n;x++)swap(a[k][x],a[i][x]);//cout<<"@@@"<<endl;
            for(int x=i+1;x<=m;x++)
            {
                if(a[x][j])
                    for(int u=0;u<=n;u++)a[x][u]^=a[i][u];
            }
        i++;
       }
       j++;
    }
    return n-i;
}

int main()
{
    get_prime();
    int t,Case=0;
    LL x;
    read(t);
    while(t--)
    {
        mst(a,0);
        m=0;
        read(n);
        For(i,1,n)
        {
            read(x);
            for(int j=1;j<=cnt;j++)
            {
                while(x%prime[j]==0){a[j][i]^=1;x/=prime[j];m=max(m,j);}
            }
        }
        n++;
        int num=gauss();

        LL ans=1;
        for(int i=1;i<=num;i++)ans=2*ans%mod;
        ans=(ans-1+mod)%mod;
        printf("Case #%d:\n%lld\n",++Case,ans);
    }
    return 0;
}

  

posted @ 2016-08-15 22:16  LittlePointer  阅读(255)  评论(0编辑  收藏  举报