B - Zhu and 772002(高斯消元解异或方程)

思路:完全平方数是指每个质因子次数均是偶数的数。现在要求n个数中选任意个使得组成得数是完全平方数,本质就是要求选的数中的每种质因子出现次数都是偶数次,而又给出最大因子是2000以内,也就是303个质因子,可以想到对每个质因子都需要满足一个异或方程(所有希望选的数对该质因子的亦或起来是0),也就是有303个方程,构造系数矩阵,用高斯消元求解。

const int N = 305,M=2000;
int Matrix[N][N];
int Free_x[N];   //自由变元
int X_Ans[N];  //解集 
int Free_num = 0;  //自由变元数
int Guass(int Row, int Col)  //系数矩阵的行和列
{
	int row = 0, col = 0, max_r;
	for (row = 0;row < Row&&col < Col;row++, col++)
	{
		max_r = row;
		for (int i = row + 1;i < Row;i++)   //找出当前列最大值
			if (abs(Matrix[i][col]) > abs(Matrix[max_r][col]))
				max_r = i;
		if (Matrix[max_r][col] == 0)  //记录自由变元
		{
			row--;
			Free_x[Free_num++] = col + 1;
			continue;
		}
		if (max_r != row)  //交换
			for (int i = col;i < Col + 1;i++)
				swap(Matrix[row][i], Matrix[max_r][i]);
		for (int i = row + 1;i < Row;i++)   //消元
		{
			if (Matrix[i][col] != 0)
			{
				for (int j = col;j < Col + 1;j++)
					Matrix[i][j] ^= Matrix[row][j];
			}
		}
	}
	ll ans = quickmod(2, Col - row, mod) - 1;
	return ans;
	for (int i = row;i < Row;i++)   //无解
		if (Matrix[i][Col] != 0)
			return 0;

	if (row < Col)   //无穷多解
	{
		ll ans = quickmod(2, Col - row, mod) - 1;
		return ans;
	}
	//唯一解
	for (int i = Col - 1;i >= 0;i--)
	{
		X_Ans[i] = Matrix[i][Col];
		for (int j = i + 1;j < Col;j++)
			X_Ans[i] ^= (Matrix[i][j] && X_Ans[j]);
	}
	return 1;
}
int p[M+1], cnt;
bool vis[M + 1];
void x_x()
{
	f(i, 2, M)
	{
		if (!vis[i])p[++cnt] = i;
		for (int j = 1;p[j] <= M / i;j++)
		{
			vis[p[j] * i] = true;
			if (i%p[j] == 0)break;
		}
	}
}
int main()
{
	//freopen("in.txt", "r", stdin);
	x_x();
	//debug(cnt);//303
	int cas = 0;
	int t = in();
	while (t--)
	{
		//memset(Matrix, 0, sizeof Matrix);
		int n = in();
		f(i, 0, n-1)
		{
			ll x;
			scanf("%lld", &x);
			f(j, 1, 303)
			{
		
				int num = 0;
				while (x%p[j] == 0)
				{
					num ^= 1;
					x /= p[j];
				}
				Matrix[j - 1][i] = num;
			}
		}
		ll ans=Guass(303, n);
		printf("Case #%d:\n%d\n", ++cas, ans);
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值