您的位置:首页 > 其它

SGU 200.Cracking RSA(高斯消元)

2014-10-24 23:00 381 查看
时间限制: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);
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: