【HDU 5833】【异或方程组高斯消元】Zhu and 772002

传送门: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): 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 .
 

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
 

Author
UESTC
 

Source
 

Recommend
wange2014   |   We have carefully selected several similar problems for you:   5906  5905  5904  5903  5902 

题意:

有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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值