ccpc网赛卡住的一道题
蓝书上的原题 但是当时没看过蓝书
今天又找出来看看 其实也不是特别懂 但比以前是了解了一点了
主要还是要想到构造异或方程组 异或方程组的消元只需要xor就好搞了
数学真的是硬伤啊……
(链接:蓝书161页详细讲解 我也在看……
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 #include<string> 7 #define cl(a,b) memset(a,b,sizeof(a)) 8 #define debug(x) cerr<<#x<<"=="<<(x)<<endl 9 using namespace std; 10 typedef long long ll; 11 12 const int maxn=3e2+10; 13 const int maxx=2e3+10; 14 const int mod=1e9+7; 15 16 int n,maxp,tol; 17 int prime[maxn]; 18 int A[maxn][maxn]; 19 20 ll powmod(ll a,ll x) 21 { 22 ll t=1; 23 while(x) 24 { 25 if(x&1) t=t*a%mod; 26 a=a*a%mod; 27 x>>=1; 28 } 29 return t; 30 } 31 32 void init() 33 { 34 bool notprime[maxx]; 35 cl(notprime,false); 36 notprime[0]=notprime[1]=true; 37 for(int i=0; i<maxx; i++) 38 { 39 if(!notprime[i]) 40 { 41 if(i*i>maxx) continue; 42 for(int j=i*i; j<maxx; j+=i) 43 notprime[j]=true; 44 } 45 } 46 tol=0; 47 for(int i=2; i<maxx; i++) 48 if(!notprime[i]) prime[tol++]=i; 49 } 50 51 ll Gauss(int m) 52 { 53 int i=0,j=0,r; 54 while(j<m&&i<n) 55 { 56 r=i; 57 for(int k=i; k<m; k++) 58 if(A[k][j]){r=k;break;} 59 if(A[r][j]){ 60 if(r!=i) for(int k=0; k<=n; k++) swap(A[r][k],A[i][k]); 61 for(int u=i+1; u<m; u++) if(A[u][j]) 62 for(int k=i; k<=n; k++) A[u][k]^=A[i][k]; 63 i++; 64 } 65 j++; 66 } 67 return i; 68 } 69 70 int main() 71 { 72 int T,cas=1; 73 scanf("%d",&T); 74 init(); 75 while(T--) 76 { 77 int maxp=0; 78 ll x; 79 scanf("%d",&n); 80 memset(A,0,sizeof(A)); 81 for(int i=0; i<n; i++) 82 { 83 scanf("%lld",&x); 84 for(int j=0; j<tol; j++) 85 { 86 while(x%prime[j]==0) 87 { 88 maxp=max(maxp,j); 89 x/=prime[j]; 90 A[j][i]^=1; 91 } 92 } 93 } 94 ll r=Gauss(maxp+1); 95 ll tmp=n-r; 96 ll ans=powmod(2,tmp)-1; 97 printf("Case #%d: ",cas++); 98 printf("%lld ",ans); 99 } 100 return 0; 101 } 102 103 /* 104 105 3 106 4 107 4 6 10 15 108 3 109 3 3 4 110 3 111 2 2 2 112 113 */