2020ICPC济南 A.Matrix Equation(高斯消元)

题意:

定 义 两 种 01 矩 阵 矩 阵 运 算 : 定义两种01矩阵矩阵运算: 01:
( 1 ) Z = X × Y , Z i , j = ( ∑ k = 1 n X i , k Y k , j ) % 2 (1)Z=X×Y,Z_{i,j}=(\sum_{k=1}^nX_{i,k}Y_{k,j})\%2 (1)Z=X×Y,Zi,j=(k=1nXi,kYk,j)%2
( 2 ) Z = X ⊙ Y , Z i , j = X i , j Y i , j (2)Z=X⊙Y,Z_{i,j}=X_{i,j}Y_{i,j} (2)Z=XY,Zi,j=Xi,jYi,j
给 定 n ∗ n 的 01 矩 阵 矩 阵 A 和 B 给定n*n的01矩阵矩阵A和B nn01AB
问 有 多 少 个 n ∗ n 的 01 矩 阵 矩 阵 C , 满 足 A × C = B ⊙ C 问有多少个n*n的01矩阵矩阵C,满足A×C=B⊙C nn01C,A×C=BC
数 据 范 围 : n < = 200 数据范围:n<=200 :n<=200

解法:

A × C = B ⊙ C A×C=B⊙C A×C=BC

∑ k = 1 n A i , k C k , j = B i , j C i , j \sum_{k=1}^nA_{i,k}C_{k,j}=B_{i,j}C_{i,j} k=1nAi,kCk,j=Bi,jCi,j

对 于 每 一 个 j , 有 : 对于每一个j,有: j,:

( A 1 , 1 C 1 , j + A 1 , 2 C 2 , j + . . . . A 1 , n C n , j ) % 2 = B 1 , j C 1 , j (A_{1,1}C_{1,j}+A_{1,2}C_{2,j}+....A_{1,n}C_{n,j})\%2=B_{1,j}C_{1,j} (A1,1C1,j+A1,2C2,j+....A1,nCn,j)%2=B1,jC1,j

( A 2 , 1 C 2 , j + A 2 , 2 C 2 , j + . . . . A 2 , n C n , j ) % 2 = B 2 , j C 2 , j (A_{2,1}C_{2,j}+A_{2,2}C_{2,j}+....A_{2,n}C_{n,j})\%2=B_{2,j}C_{2,j} (A2,1C2,j+A2,2C2,j+....A2,nCn,j)%2=B2,jC2,j

. . . ... ...

% 2 加 法 就 是 异 或 , 所 以 式 子 可 以 变 成 : \%2加法就是异或,所以式子可以变成: %2,:

A 1 , 1 C 1 , j ⊕ A 1 , 2 C 2 , j ⊕ . . . . A 1 , n C n , j = B 1 , j C 1 , j A_{1,1}C_{1,j}⊕A_{1,2}C_{2,j}⊕....A_{1,n}C_{n,j}=B_{1,j}C_{1,j} A1,1C1,jA1,2C2,j....A1,nCn,j=B1,jC1,j

A 2 , 1 C 1 , j ⊕ A 2 , 2 C 2 , j ⊕ . . . . A 2 , n C n , j = B 2 , j C 2 , j A_{2,1}C_{1,j}⊕A_{2,2}C_{2,j}⊕....A_{2,n}C_{n,j}=B_{2,j}C_{2,j} A2,1C1,jA2,2C2,j....A2,nCn,j=B2,jC2,j

. . . ... ...

如 果 B i , j = 0 , 那 么 式 子 右 边 就 是 0 如果B_{i,j}=0,那么式子右边就是0 Bi,j=0,0

如 果 B i , j = 1 , 那 么 左 右 同 时 异 或 C 2 , j , 如果B_{i,j}=1,那么左右同时异或C_{2,j}, Bi,j=1,C2,j,

右 边 变 成 0 , 左 边 a i , i = 1 右边变成0,左边a_{i,i}=1 0,ai,i=1

那 么 式 子 右 边 就 变 成 0 , 左 边 的 A j , j = A j , j ⊕ 1 那么式子右边就变成0,左边的A_{j,j}=A_{j,j}⊕1 0,Aj,j=Aj,j1

对 于 每 个 j , 用 高 斯 消 元 分 别 计 算 出 异 或 方 程 组 自 由 元 的 个 数 对于每个j,用高斯消元分别计算出异或方程组自由元的个数 j,

设 n 列 的 自 由 元 总 个 数 为 c n t , 那 么 答 案 为 2 c n t 设n列的自由元总个数为cnt,那么答案为2^{cnt} ncnt,2cnt

code:

#include <bits/stdc++.h>
using namespace std;
const int maxm=1e3+5;
const int mod=998244353;
int ppow(int a,int b,int mod){
    
    
    int ans=1%mod;a%=mod;
    for(;b;b>>=1,a=1LL*a*a%mod)if(b&1)ans=1LL*ans*a%mod;
    return ans;
}
int A[maxm][maxm];
int B[maxm][maxm];
int n;
//
int a[maxm][maxm],x[maxm];
int freedom[maxm],num;//存储自由元的位置
int Gauss(int m,int n){
    
    //m为行数,n为列数(不含常数列)
    int col=0,k=0;//col为列号,k为行号
    for(;k<m&&col<n;k++,col++){
    
    
        int r=k;
        for(int i=k+1;i<m;i++){
    
    //找系数最大的列
            if(abs(a[i][col])>a[r][col])r=i;
        }
        if(a[r][col]==0){
    
    //如果一列都为0就跳过
            freedom[num++]=col;//存储自由元的列数
            k--;continue;
        }
        if(r!=k)for(int i=col;i<=n;i++){
    
    //交换行
            swap(a[k][i],a[r][i]);
        }
        for(int i=k+1;i<m;i++){
    
    //消元
            if(abs(a[i][col])!=0){
    
    
                for(int j=col;j<=n;j++){
    
    
                    a[i][j]^=a[k][j];
                }
                //a[i][j]=0;
            }
        }
    }
    for(int i=k;i<m;i++){
    
    
        if(a[i][col]!=0)return -1;//无解标志
    }
    if(k<n)return n-k;//如果有自由元,返回自由元个数
    for(int i=n-1;i>=0;i--){
    
    
        x[i]=a[i][n];
        for(int j=i+1;j<n;j++){
    
    
            x[i]^=(a[i][j]&&x[j]);
        }
    }
    return 0;//有解标志
}
signed main(){
    
    
    scanf("%d",&n);
    for(int i=0;i<n;i++){
    
    
        for(int j=0;j<n;j++){
    
    
            scanf("%d",&A[i][j]);
        }
    }
    for(int i=0;i<n;i++){
    
    
        for(int j=0;j<n;j++){
    
    
            scanf("%d",&B[i][j]);
        }
    }
    int cnt=0;
    for(int p=0;p<n;p++){
    
    
        for(int i=0;i<n;i++){
    
    
            for(int j=0;j<n;j++){
    
    
                a[i][j]=A[i][j];
            }
            if(B[i][p]==1)a[i][i]^=1;
        }
        int temp=Gauss(n,n);
        if(temp==-1){
    
    
            puts("0");
            return 0;
        }
        cnt+=temp;
    }
    int ans=ppow(2,cnt,mod);
    printf("%d\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44178736/article/details/112929971
今日推荐