sgu200:Cracking RSA(模意义下高斯消元求自由变元个数)

来源:互联网 发布:linux端口查询命令 编辑:程序博客网 时间:2024/05/21 22:47

题意:

有b个数,每个数经质因数分解后质因子都是是质数表中前t个质数中的一个。

给出序列b,正整数t,我们从b中选若干个数乘起来得到一个积,问有多少种取法使得积为完全平方数。

分析:

要使积为完全平方数,那么分解后每个质数出现次数为偶数次。

我们可以以每一个质数作为一个方程,g[i][j]表示第i个质数在bj中出现的次数,解这个模2线性方程组即可。

设自由元个数为k,那么答案为2^k-1,除去什么都不选。

#include <cstdio>#include <bitset>#include <cstring>#include <iostream>#include <algorithm>using namespace std;typedef long long LL;const int MAXT = 109, MAXM = 109;int t, m;int b[MAXM];int prime[MAXT], sum;int num;bool cap[MAXT];struct bit{int set[MAXM];}g[MAXT];void pre(){int tot = 0;bool hash[550] = {0};for(int i = 2;; ++i){if(!hash[i]) {prime[++tot] = i;if(tot == t) return ;}for(int j = 1; j <= tot && i*prime[j] < 550; ++j){hash[i*prime[j]] = true;if(i%prime[j] == 0) break;}}}int gauss(){int to = 0;for(int i = 1; i <= m; ++i){bool flag = false;for(int j = to+1; j <= t; ++j)if(g[j].set[i]){swap(g[++to], g[j]);flag = true;break;}if(flag){for(int j = to+1; j <= t; ++j)if(g[j].set[i]) {for(int k = 1; k <= m; ++k)g[j].set[k] ^= g[to].set[k];}}}return m-to;}void out(int num){int ans[105] = {1};ans[1] = 1;for(int i = 1; i <= num; ++i){for(int j = 1; j <= ans[0]; ++j)ans[j] <<= 1;for(int j = 1; j <= ans[0]; ++j)if(ans[j] > 9) {ans[j] -= 10;ans[j+1]++;}if(ans[ans[0]+1]) ans[0]++;}ans[1]--;for(int i = ans[0]; i >= 1; --i)cout << ans[i];cout << endl;}int main(){cin >> t >> m;pre();for(int i = 1; i <= m; ++i){cin >> b[i];for(int j = 1; j <= t && prime[j] <= b[i]; ++j)while(b[i]%prime[j] == 0){g[j].set[i] ^= 1;b[i] /= prime[j];}}int num = gauss();out(num);return 0;}


0 0
原创粉丝点击