UVA11524构造系数数组+高斯消元解异或方程组

  1 /*UVA11524
  2 题目:给定n个数(n<=100),从中找出1或多个数,使他们的乘积是一个完全平方数
  3 分析:转化成数理模型是第一步,肯定要分解质因数,ps:题目给定不含大于500的素因子。
  4 第二选择的数字相同质因子个数之和必须是偶数,因为之奇偶性有关,可将奇数为1,偶数为0,这样约简。
  5 然后按照常理,应该找出所有的可能性(暴力的思想),因为n<=100,不可能用状态压缩的办法,所以用下面的方法,同时也是给自己一个拓展的思路
  6 高斯消元解异或方程组:
  7 假设n个数,设数组ch[i],表式选第i的数与否,那么,列出每个质因子的总个数方程,总个数模2为0即可,因为异或等同于模2加,故列异或方程。
  8 最后自由变量假设有k个,则说明2^k-1种方案
  9 解异或方程组的思路:
 10 1、构造系数数组(0,1)
 11 Mat[i][j]:第i个质因数的方程,第j个数字的因数分解后的个数
 12 2、解异或方程Mat(n,m)//要收录
 13 
 14 int solve(int n1,int m1) //解方程部分借鉴白书,要弄明白
 15 {
 16     int i=0,j=0;
 17     while(i<n1&&j<m1)
 18     {
 19         int r=i;
 20         for(int k=i; k<n1; k++)
 21             if (A[k][j])
 22             {
 23                 r=k;
 24                 break;
 25             }
 26         if (A[r][j])
 27         {
 28             if (r!=i) for(int k=0; k<=m1; k++) swap(A[r][k],A[i][k]);
 29             for(int u=i+1; u<n1; u++) if (A[u][j])
 30                     for(int k=i; k<=m1; k++) {A[u][k]^=A[i][k];}
 31             i++;
 32         }
 33         j++;
 34     }
 35     return i;
 36 }//返回的是确定解的个数
 37 */
 38 #include<iostream>
 39 #include<stdio.h>
 40 #include<string.h>
 41 #include<algorithm>
 42 #include<stdlib.h>
 43 #include<math.h>
 44 #include<queue>
 45 #include<vector>
 46 #include<map>
 47 //#define LL long long
 48 using namespace std;
 49 
 50 bool isprim[505];
 51 int cnt;
 52 int prim[505/2];
 53 void prime_calc()
 54 {
 55     cnt=0;
 56     memset(isprim,0,sizeof(isprim));
 57     for(int i=2; i<=500; i++)
 58     {
 59         if (!isprim[i])
 60         {
 61             prim[cnt++]=i;
 62             for(int j=2*i; j<=500; j+=i) isprim[j]=1;
 63         }
 64     }
 65 }
 66 
 67 int T,n;
 68 int A[505][505];
 69 
 70 int solve(int n1,int m1) //解方程部分借鉴白书,要弄明白
 71 {
 72     int i=0,j=0;
 73     while(i<n1&&j<m1)
 74     {
 75         int r=i;
 76         for(int k=i; k<n1; k++)
 77             if (A[k][j])
 78             {
 79                 r=k;
 80                 break;
 81             }
 82         if (A[r][j])
 83         {
 84             if (r!=i) for(int k=0; k<=m1; k++) swap(A[r][k],A[i][k]);
 85             for(int u=i+1; u<n1; u++) if (A[u][j])
 86                     for(int k=i; k<=m1; k++) A[u][k]^=A[i][k];
 87             i++;
 88         }
 89         j++;
 90     }
 91     return i;
 92 }
 93 
 94 int main()
 95 {
 96     prime_calc();
 97     cin>>T;
 98 //    cout<<cnt<<endl;
 99     while(T--)
100     {
101         cin>>n;
102         int n1=0,m1=n;
103         memset(A,0,sizeof(A));
104         long long  k;
105         for(int i=0; i<n; i++)
106         {
107             cin>>k;
108             for(int j=0; j<cnt; j++){
109                 while(k%prim[j]==0) {A[j][i]^=1;n1=max(n1,j+1);k=k/prim[j];}
110             }//构造系数矩阵,系数只和奇偶性有关
111         }
112         cout<<(1LL<<(n-solve(n1,m1)))-1<<endl;//注意pow运算处理不了LL的数据,要么手写函数,要么移位运算
113     }
114     return 0;
115 }

 

posted @ 2014-02-26 21:27  little_w  阅读(312)  评论(0编辑  收藏  举报