题目链接:http://vjudge.net/contest/142484#problem/A
这个题目也是2016年CCPC网赛上面的题目,当时我是不会做的,但是大牛们都知道这是一个原题,最后给一队过了,还是大牛们厉害,其实也不是很难。
题意:
给出n个正整数,从中选出1个或者多个,使得选出来的整数乘积是完全平方数,一共有多少种选法。
分析:
"不含大于500的素数因子"——每一个数的唯一分解式。
例如: {4,6,10,15}
4x1 = 22 * 30 * 50;
6x2 = 21 * 31 * 50;
10x3= 21 * 30 * 51;
15x4 = 20* 31 * 51;
要使得乘积为平方数,那么每个分向量的指数为偶数。
就得到了方程组:
x2 + x3 = 0(mod2);
x2 + x4 = 0(mod2);
x3 + x4 = 0(mod2);
解方程:
发现有x个自由变量答案就是 2x - 1个解(全部不要题意删除);

#include <bits/stdc++.h> using namespace std; const int maxn = 500 + 10; const int maxp = 100; int vis[maxn]; int prime[maxp]; int gen_primes(int n) { int m = (int)sqrt(n+0.5); memset(vis,0,sizeof(vis)); //是素数为 0 for(int i=2; i<=m; i++) { if(!vis[i]) { for(int j=i*i; j<=n; j+=i) vis[j] = 1; } } int c = 0; for(int i=2; i<=n; i++) { if(!vis[i]) prime[c++] = i; } return c; } typedef int Matrix[maxn][maxn]; Matrix A; //m 个 方程组,n 个变元 int ranks(Matrix A,int m,int n) { int i=0,j=0,k,r,u; while(i<m&&j<n) { r = i; for(k=i; k<m; k++) if(A[k][j]) { r = k; break; } if(A[r][j]) { if(r!=i) for(k=0; k<=n; k++) { swap(A[r][k],A[i][k]); } //消元 for(u=i+1; u<m; u++) { if(A[u][j]) for(k=i; k<=n; k++) A[u][k] ^=A[i][k]; } i++; } j++; } return i; } int main() { int m = gen_primes(500); int t; scanf("%d",&t); while(t--) { int n,maxp = 0; long long x; scanf("%d",&n); memset(A,0,sizeof(A)); for(int i=0; i<n; i++) { scanf("%lld",&x); for(int j=0; j<m; j++) //对于某一个素数因子 { while(x%prime[j]==0) { maxp = max(maxp,j); //方程组 x = x/prime[j]; A[j][i]^=1; } } } int r = ranks(A,maxp+1,n); printf("%lld ",(1LL<<(n-r))-1); } return 0; }