Description
给出一个n*n的矩阵,求有多少种选择数的方案,使得每行每列均选择了奇数个数,并且选择的数的乘积为完全平方数
n<=20
Solution
完全平方数是什么,就是所有质因子的出现次数均为偶数
这样就变成了一堆奇偶的限制,异或方程组求自由元个数
高斯消元即可
感觉自己之前又打了假的高斯消元
Code
#include <cstdio>
#include <cstring>
#include <algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
#define P(x,y) ((x-1)*n+y)
const int N=905,P=9*N+2*N+5,Mo=1e9+7;
struct Prime{int p,r,bl;}pri[P];
bool cmp(Prime x,Prime y) {return x.p<y.p;}
int n,x,tot,num,ty;
bool f[P][N];
int main() {
for(scanf("%d",&ty);ty;ty--) {
scanf("%d",&n);tot=0;
fo(i,1,n)
fo(j,1,n) {
scanf("%d",&x);
for(int k=2;k*k<=x;k++) {
if (!(x%k)) pri[++tot].p=k,pri[tot].bl=P(i,j),pri[tot].r=0;
while (!(x%k)) x/=k,pri[tot].r++;
}
if (x>1) pri[++tot].p=x,pri[tot].bl=P(i,j),pri[tot].r=1;
}
sort(pri+1,pri+tot+1,cmp);
memset(f,0,sizeof(f));num=0;
fo(i,1,n) {
num++;
fo(j,1,n) f[num][P(i,j)]=1;
f[num][0]=1;
}
fo(i,1,n) {
num++;
fo(j,1,n) f[num][P(j,i)]=1;
f[num][0]=1;
}
fo(i,1,tot) {
if (pri[i].p!=pri[i-1].p) {
num++;
fo(j,0,n*n) f[num][j]=0;
}
f[num][pri[i].bl]=pri[i].r%2;
}
int pos=1,ans=1;
fo(i,1,n*n) {
int now=-1;
fo(j,pos,num) if (f[j][i]) {now=j;break;}
if (now==-1) ans=(ans<<1)%Mo;
else swap(f[now],f[pos]),pos++;
fo(j,pos,num)
if (f[j][i])
fo(k,0,n*n)
f[j][k]^=f[pos-1][k];
}
bool ok=1;
fo(i,1,num) {
bool now=0;
fo(j,1,n*n) if (f[i][j]) {now=1;continue;}
if (!now&&f[i][0]) {ok=0;break;}
}
if (!ok) {printf("0\n");continue;}
printf("%d\n",ans);
}
}