HDU - 5833: Zhu and 772002 (高斯消元-自由元)
pro:给定N个数Xi(Xi<1e18),保证每个数的素因子小于2e3;问有多少种方案,选处一些数,使得数的乘积是完全平方数。求答案%1e9+7; N<300;
sol:小于2e3的素数只有304个。选或者不选看成1和0,那么问题其实就是问%2意义下的自由元。 答案是2^自由元
#include<bits/stdc++.h> #define ll long long #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int maxn=2010; const int Mod=1e9+7; int a[340][340],vis[maxn],p[340],tot; void prime() { for(int i=2;i<maxn;i++){ if(!vis[i]) p[tot++]=i; for(int j=1;j<=tot&&p[j-1]*i<maxn;j++){ vis[i*p[j-1]]=1; if(i%p[j-1]==0) break; } } } int Gauss(int N,int M) { int free=0; for(int i=0,p=0;i<N&&p<M;i++,p++){ int t=i; rep(j,i+1,N-1) if(a[j][p]>a[t][p]) t=j; if(!a[t][p]){ i--; free++; continue;} if(i!=t) rep(j,p,M) swap(a[i][j],a[t][j]); rep(j,i+1,N-1){ if(!a[j][p]) continue; rep(k,p,M) a[j][k]^=a[i][k]; } } return free; } int main() { prime(); int T,N,num,C=0; ll x; scanf("%d",&T); while(T--){ memset(a,0,sizeof(a)); scanf("%d",&N); rep(i,0,N-1) { scanf("%lld",&x); rep(j,0,tot-1){ ll tx=x; while(tx%p[j]==0){ tx/=p[j]; a[j][i]^=1; } } } int t=Gauss(tot,N); int res=1; rep(i,1,t) res=res*2%Mod; printf("Case #%d:\n%d\n",++C,(res+Mod-1)%Mod); } return 0; }
It is your time to fight!