UVA 11542 - Square
题意:给定一些数字。保证这些数字质因子不会超过500,求这些数字中选出几个,乘积为全然平方数,问有几种选法
思路:对每一个数字分解成质因子后。发现假设要是全然平方数,选出来的数字的每一个质因子个数都必定要是偶数,这样每一个质因子能够列出一个异或的方程,假设数字包括质因子,就是有这个未知数,然后进行高斯消元,求出自由变量的个数,每一个自由变量能够选或不选。这种情况就是(2^个数),然后在扣掉什么都不选的1种就是答案了
代码:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const long long N = 501; int t, n, a[N][N], Max, vis[N], pn = 0; long long prime[N]; void get_prime() { for (long long i = 2; i < N; i++) { if (vis[i]) continue; prime[pn++] = i; for (long long j = i * i; j < N; j += i) vis[j] = 1; } } int gauss() { int i = 0, j = 0; while (i <= Max && j < n) { int k = i; for (; k <= Max; k++) if (a[k][j]) break; if (k != Max + 1) { for (int l = 0; l <= n; l++) swap(a[i][l], a[k][l]); for (int k = i + 1; k <= Max; k++) { if (a[k][j]) { for (int l = j; l <= n; l++) a[k][l] ^= a[i][l]; } } i++; } j++; } return n - i; } int main() { get_prime(); scanf("%d", &t); while (t--) { scanf("%d", &n); long long x; Max = 0; memset(a, 0, sizeof(a)); for (int i = 0; i < n; i++) { scanf("%lld", &x); for (int j = 0; j < pn && prime[j] <= x; j++) { while (x % prime[j] == 0) { a[j][i] ^= 1; Max = max(Max, j); x /= prime[j]; } } } printf("%lld ", (1LL<<(gauss())) - 1); } return 0; }