【JZOJ3823】遇见

Description

Zyh独自一人在街上漫步。Zyh相信不久后应该就可以和她一起漫步,可是去哪里寻找那个她呢?Zyh相信每个人都有一个爱情的号码牌,这个号码牌是一个n*n的矩阵。
每个人都要在矩阵中选择若干个元素,使得每行每列都有奇数个数被选中,且选中的数字的乘积是完全平方数。每当选出了这若干个元素,他/她就能找到那个她/他。
Zyh想知道对于一个号码牌有多少种选择的方法,使得zyh能够不再孤独。由于这个数字很大,只要输出对1,000,000,007取模后的余数即可。

Solution

我们设 Pi,j 表示 (i,j) 这个格子选不选。

现在有两个条件:
1. 使得每行每列都有奇数个数被选中
2. 选中的数字的乘积是完全平方数

我们先看条件1,那么要满足:
Pi,1Pi,2Pi,n=1(1in)
P1,jP2,jPn,j=1(1jn)
(这里的⊕是异或的意思)

再看条件2:
我们把所有数分解质因数,记出现的质数为 p1,p2,,pm

定义 f(k,x) 表示 x 这个数是包含了奇数还是偶数个第k个质数因子,分别用1或0表示。

举个例子:
72=2332
那么 f(2,72)=1,f(3,72)=0

然后对于第 k 个质数,我们可以得出式子:
P1,1f(pk,a1,1)P1,2f(pk,a1,2)Pn,nf(pk,an,n)=0

然后我们得出了一些式子,这就是很经典的异或方程组模型,用高斯消元求自由元个数 t ,答案就是2t

Code

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
#define rep(i,x) for(int i=ls[x];i;i=nx[i])
#define N 31
#define M 3001
#define ll long long
#define mo 1000000007
#define mod 300007
using namespace std;
int a[M][N*N];
int n;
int bh[M][N*N];
int pr[M];
int h[mod],wz[mod];
int w;
bool hash(int x)
{
    int p=x%mod;
    while(h[p] && h[p]!=x) p=(p+1)%mod;
    w=p;
    if(h[p]==x) return true;
    return false;
}
int g(int x,int y){
    return (x-1)*n+y;
}
int gauss(int tot,int m)
{
    int i=0,j=0;
    while(i<m && j<tot)
    {
        int r=i;
        fo(k,i,m) if(a[k][j]) {r=k;break;}
        if(a[r][j])
        {
            if(r!=i)
            fo(k,0,tot) swap(a[i][k],a[r][k]);
            fo(l,i+1,m-1) if(a[l][j])
            fo(k,i,tot) a[l][k]^=a[i][k];
            int t=0;
            i++;
        }
        j++;
    }
    fo(i,0,m-1)
    {
        int t=0;
        fo(j,0,tot-1) t+=a[i][j];
        if(!t && a[i][tot]==1) return -1;
    }
    return i;
}
int main()
{
    scanf("%d",&n);
    fo(i,1,n)
    fo(j,1,n)
    {
        ll x;
        scanf("%lld",&x);
        int p=2;
        while(p*p<=x)
        {
            int t=0;
            bool tf=hash(p);
            if(x%p==0 && !tf)
            {
                pr[++pr[0]]=p;
                wz[w]=pr[0];
                h[w]=p;
            }
            while(x%p==0) x/=p,t^=1;
            bh[wz[w]][g(i,j)]=t;
            p++;
        }
        if(x>1)
        {
            bool tf=hash(x);
            if(!tf)
            {
                pr[++pr[0]]=x;
                wz[w]=pr[0];
                h[w]=x;
            }
            bh[wz[w]][g(i,j)]=1;
        }
    }
    int m=0;
    fo(i,1,n)
    {
        fo(j,1,n) a[m][g(i,j)-1]=1;
        a[m][n*n]=1;
        m++;
    }
    fo(j,1,n)
    {
        fo(i,1,n) a[m][g(i,j)-1]=1;
        a[m][n*n]=1;
        m++;
    }
    fo(p,1,pr[0])
    {
        fo(i,1,n)
        fo(j,1,n)
        a[m][g(i,j)-1]=bh[p][g(i,j)];
        a[m][n*n]=0;
        m++;
    }
    int t=n*n-gauss(n*n,m);
    if(t==n*n+1)
    {
        printf("0");
        return 0;
    }
    ll ans=1;
    fo(i,1,t) ans=ans*2%mo;
    printf("%lld",ans);
}
posted @ 2017-01-15 21:30  sadstone  阅读(61)  评论(0编辑  收藏  举报