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