题目大意:
给你一个t,m,接下来输入m个数a1。。。。am满足ai的质因数包含在前t个质数中
从中取出任意个数,使得乘积为完全平方数,问有多少种取法。
解题思路:
思路很简单,因为要是完全平方数,然后质因子的范围也知道,所以我们可以对每个质因子列出一个模意义下的方程(mod 2),然后求变元的个数就行了,ans=2^num-1(去掉全部为0)
如何求变元的个数,也很简单,就是在高斯消元的时候对于一个未知数xi,如果后面的方程xi的系数都为0的话,那么这个就是一个变元
AC代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
int prime[110]={0};
int cnt,flag[11000]={0};
int m,t;
int a[110]={0};
int fc[110][110]={{0}};
int num=0;
void Init()
{
for(int i=2;i<=1000;i++){
if(flag[i]) continue;
prime[++cnt]=i;
if(cnt==t+1) return ;
for(int j=2;j*i<=1000;j++)
flag[i*j]=1;
}
}
void change(int k,int g)
{
for(int i=1;i<=t;)
{
if(k%prime[i]==0)
{
fc[i][g]^=1;
k/=prime[i];
}
else i++;
}
return;
}
void prt()
{
int ans[1010]={0};
ans[0]=ans[1]=1;
for(int i=1;i<=num;i++)
{
for(int j=1;j<=ans[0];j++)
{
ans[j]*=2;
if(j>1)
{
ans[j]+=ans[j-1]/10;
ans[j-1]%=10;
}
}
for(;ans[ans[0]]>=10;)
{
ans[0]++;
ans[ans[0]]+=ans[ans[0]-1]/10;
ans[ans[0]-1]%=10;
}
}
ans[1]--;
for(int i=ans[0];i>=1;i--)
printf("%d",ans[i]);
return;
}
int done()
{
int g=0;
int i,j;
for(j=1;j<=m && g<t;j++)
{
for(i=g+1;i<=t;i++)
if(fc[i][j]==1)
break;
if(i<=t)
{
g++;
for(int p=j;p<=m;p++)
swap(fc[g][p],fc[i][p]);
for(int p=g+1;p<=t;p++)
{
if(fc[p][j]==1)
{
for(int q=j;q<=m;q++)
fc[p][q]^=fc[g][q];
}
}
}
}
return m-g;
}
int main()
{
cin>>t>>m;
Init();
for(int i=1;i<=m;i++)
{
scanf("%d",&a[i]);
change(a[i],i);
}
num=done();
prt();
return 0;
}