SGU 200.Cracking RSA(高斯消元)
时间限制:0.25s
空间限制:4M
题意:
给出了m(<100)个数,这m个数的质因子都是前t(<100)个质数构成的。
问有多少个这m个数的子集,使得他们的乘积是完全平方数。
Solution:
要使乘积为完全平方数,那么对于乘积的每个质因子的个数要为偶数。
可以先打出前100个质数,来看第i个质数Pi,对于第j个数Kj,如果它含有奇数个质数Pi,那么矩阵A[i][j]的值为1,显然增广矩阵的值应该全为0.
这样就构造出了一个n*m的xor方程组.
利用高斯消元求出变元的个数power
那么答案就是(2^power)-1
wa了几次竟然是因为高精度写错了,真是醉了...
code
/* 解异或方程组 */ #include <iostream> #include <vector> using namespace std; const int MAXN = 211; int prim[MAXN]; vector<int> A[MAXN]; int Gauss (int n, int m) { int col = 1, row = 0, tem, k = 0; for (; col <= m && row <= n; ++col) { for (tem = ++row; tem <= n && A[tem][col] == 0; ++tem); if (tem > n) { row--; continue; } if (tem != row) swap (A[tem], A[row]); for (int i = row + 1; i <= n; ++i) { if (A[i][col]) for (int j = col; j <= m; ++j) A[i][j] ^= A[row][j]; } } return m - row; } void init() { bool vis[2200] = {0}; for (int i = 2, tol = 0; i <= 1000; ++i) if (!vis[i]) { prim[++tol] = i; for (int j = i; j <= 1000; j += i) vis[j] = 1; } } int n, m; void output (int x) { if (x <= 0) { cout << 0 << endl; return; } int C[1000] = {0}, len = 1; for (int i = 1; i <= x; ++i) { for (int j = 1; j <= len; ++j) C[j] <<= 1; C[1]++; for (int t = 1; t <= len ; t++) if (C[t] >= 10) { C[t + 1] += C[t] / 10; C[t] %= 10; if (t + 1 > len) len++; } } for (int i = len; i > 0; --i) cout << C[i]; } int main() { ios::sync_with_stdio (0); init(); cin >> n >> m; for (int i = 1; i < MAXN; i++) A[i].resize (MAXN); for (int i = 1, x; i <= m; ++i) { cin >> x; for (int j = 1; j <= n; ++j) for (; x % prim[j] == 0; x /= prim[j]) A[j][i] ^= 1; } int power = Gauss (n, m); output (power); }