【51nod 1323】【JZOJ 3823】 遇见

Description

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

对于100%的数据 n<=30 Aij<=1000000000

Analysis

考虑约束:
1.每行每列都有奇数个数被选中
2.选中的数字的乘积是完全平方数
完全平方数启示我们对每个数分解质因数,指数只用保留0或1
然后可以列出方程组,设X[i,j]表示第i行第j列的数选或不选
那么对于每一行,每一列,显然是该行的X异或起来值为1
对于每个质数,那就是每格质数的指数*X异或起来值为0
于是可以解异或方程组
因为不同质数不是太多,不知道有没有1000个
高斯消元三次方看起来依然很虚,但是未知数的系数为1的很少,所以复杂度远远达不到三次方
那么答案就是2
如何判定自由元?
如果方程已经全部用完了,但是还有许多未知数剩,那这些未知数肯定是自由元
如果某个未知数没有一个系数为1,那么X取0或1都可以,所以也是自由元
如何判定方程无解?
如果一个方程系数全为0,答案却为1,则显然出现矛盾,无解
只有这一种情况吗?是的,因为其他等价情况消元后等价于上述情况

Code

#include<cstdio>
#include<cmath>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,b,a) for(int i=b;i>=a;i--)
#define num(i,j) ((((i)-1)*n)+(j))
using namespace std;
const int N=35,mo=1e9+7;
int n,m,c[N][N],p[5000],pri[10000],a[5000][N][N];
int mat[5065][N*N];
long long ans;
void prepare()
{
    scanf("%d",&n);
    fo(i,1,n)
        fo(j,1,n)
        {
            scanf("%d",&c[i][j]);
            int x=c[i][j];
            for(int k=2;k*k<=x;k++)
                if(x%k==0)
                {
                    pri[++pri[0]]=k;
                    while(x%k==0) x/=k;
                }
            if(x>1) pri[++pri[0]]=x;
        }
    sort(pri+1,pri+pri[0]+1);
    fo(i,1,pri[0])
        if(pri[i]!=pri[i-1]) p[++p[0]]=pri[i];
    fo(i,1,n)
        fo(j,1,n)
        {
            int x=c[i][j];
            fo(k,1,p[0])
                while(x%p[k]==0) a[k][i][j]^=1,x/=p[k];
        }
}
void makemat()
{
    fo(i,1,n)
    {
        mat[i][0]=1;
        fo(j,1,n) mat[i][num(i,j)]=1;
    }
    fo(i,1,n)
    {
        mat[n+i][0]=1;
        fo(j,1,n) mat[n+i][num(j,i)]=1;
    }
    m=n+n;
    fo(k,1,p[0])
    {
        mat[++m][0]=0;
        fo(i,1,n)
            fo(j,1,n) mat[m][num(i,j)]=a[k][i][j];
    }
}
void gauss()
{
    int num=0;
    ans=1;
    int pos=1;
    fo(i,1,n*n)
    {
        bool q=0;
        fo(j,pos,m)
            if(mat[j][i])
            {
                swap(mat[pos],mat[j]),q=1;
                break;
            }
        if(!q) num++;
        else pos++;
        fo(j,pos,m)
            if(mat[j][i])
                fo(k,0,n*n) mat[j][k]^=mat[pos-1][k];
    }
    fo(i,1,m)
    {
        bool q=0;
        fo(j,1,n*n)
            if(mat[i][j]) {q=1;break;}
        if(q) continue;
        if(mat[i][0]) ans=0;
    }
    fo(i,1,num) ans=ans*2%mo;
}
int main()
{
    prepare();
    makemat();
    gauss();
    printf("%lld\n",ans);
    return 0;
}
内容概要:本文档是一份关于交换路由配置的学习笔记,系统地介绍了网络设备的远程管理、交换机与路由器的核心配置技术。内容涵盖Telnet、SSH、Console三种远程控制方式的配置方法;详细讲解了VLAN划分原理及Access、Trunk、Hybrid端口的工作机制,以及端口镜像、端口汇聚、端口隔离等交换技术;深入解析了STP、MSTP、RSTP生成树协议的作用与配置步骤;在路由部分,涵盖了IP地址配置、DHCP服务部署(接口池与全局池)、NAT转换(静态与动态)、静态路由、RIP与OSPF动态路由协议的配置,并介绍了策略路由和ACL访问控制列表的应用;最后简要说明了华为防火墙的安全区域划分与基本安全策略配置。; 适合人群:具备一定网络基础知识,从事网络工程、运维或相关技术岗位1-3年的技术人员,以及准备参加HCIA/CCNA等认证考试的学习者。; 使用场景及目标:①掌握企业网络中常见的交换与路由配置技能,提升实际操作能力;②理解VLAN、STP、OSPF、NAT、ACL等核心技术原理并能独立完成中小型网络搭建与调试;③通过命令示例熟悉华为设备CLI配置逻辑,为项目实施和故障排查提供参考。; 阅读建议:此笔记以实用配置为主,建议结合模拟器(如eNSP或Packet Tracer)动手实践每一条命令,对照拓扑理解数据流向,重点关注VLAN间通信、路由选择机制、安全策略控制等关键环节,并注意不同设备型号间的命令差异。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值