您的位置:首页 > 其它

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

2015-01-21 18:43 417 查看
题意:

有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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: