这题就是先转化成异或方程组,再用高斯消元求解矩阵的秩,然后就可以求出个数了.
对我这个初学者来说,我觉得自己上面这波逼装的,可以给满分。
看了别人的代码,感觉本题的思路主要是,先找出0~2000中所有的质数,然后依次读取每一个数,将其分解为很多个质数乘积的形式,并存入数组(要注意的是那个保存数据的数组每一行代表的是某一个质数在各个读取的书中有几个,而每一列代表一个数可以被分成多少个质数,每个质数有多少个),同时只需要0和1来代表个数就行了,因为偶数个的可以直接约去,这时我们视其为一个方程组,要使每一行的解为0,所以根据线性代数里面教的,就依次把每一行的第一个化为1,化完之后,会有多个数字并不在每一行的开头,那么这些数字就是无法确定的点,有两种情况,因为根据后面的点的选取就可以确定每一行开头那点的数值,所以2的n次方(n为无法确定的点的个数),就是所有可能的情况,又因为我们要排除所有点都没取的情况,所以说要再减去1,那就是结果了。
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; int prime[500]; bool number[2000+10]; int shuzu[500][310]; int num=0; __int64 a[310]; void init() { memset(number,true,sizeof(number)); int i,j; for(i=2;i<=2000;i++) { if(number[i]) { prime[num++]=i; for(j=i;j<=2000;j=j+i) { number[j]=false; } } } } void trans(int i) { __int64 pre=a[i]; int j; for(j=0;j<num;j++) { while((pre%prime[j]==0)) { shuzu[j][i]^=1; pre=pre/prime[j]; } if(pre==0) break; } } __int64 pow(int x,int n) { __int64 temp(x),res(1); while(n) { if(n&1) { res =(res*temp)%1000000007; } temp =(temp*temp)%1000000007; n>>=1; } return res; } __int64 solve(int num,int n) { int i=0,j=0,k,r,u; while(i<num&&j<n) { for(k=i;k<num;k++) { if(shuzu[k][j]) { r=k; break; } } if(shuzu[k][j]) { if(r!=i) { for(u=0;u<n;u++) swap(shuzu[i][u],shuzu[r][u]); } for(k=r+1;k<num;k++) { if(shuzu[k][j]) { for(u=j;u<n;u++) shuzu[k][u]^=shuzu[i][u]; } } i++; } j++; } return pow(2,n-i)-1; } int main() { int t; scanf("%d",&t); int icase; init(); for(icase=1;icase<=t;icase++) { memset(shuzu,0,sizeof(shuzu)); int n; scanf("%d",&n); int i; for(i=0;i<n;i++) { scanf("%I64d",&a[i]); trans(i); } __int64 ans=solve(num,n); printf("Case #%d:\n",icase); printf("%I64d\n",ans); } return 0; }
