zoukankan      html  css  js  c++  java
  • 第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(济南)A. Matrix Equation(高斯消元)

    链接:https://ac.nowcoder.com/acm/contest/10662/A
    来源:牛客网

    We call a matrix "01 Square" if and only if it's a N×NN×N matrix and its elements are all 00 or 11.

    For two 01 Squares XX,YY, we define two operators X×YX×Y and X⊙YX⊙Y. The value of them are also 01 Square matrices and calculated below(we use ZZ to abbreviate X×YX×Y and DD to abbreviate X⊙YX⊙Y):

    Zi,j=(∑k=1NXi,kYk,j) mod 2Zi,j=(∑k=1NXi,kYk,j) mod 2

    Di,j=Xi,jYi,jDi,j=Xi,jYi,j

    Now MianKing has two 01 Squares A,BA,B, he wants to solve the matrix equation below:

    A×C=B⊙CA×C=B⊙C

    You need to help MainKing solve this problem by calculating how many 01 Squares CC satisfy this equation.

    The answer may be very large, so you only need to output the answer module 998244353998244353.

    输入描述:

    The first line has one integer NN
    
    Then there are NN lines and each line has NN integers, the j-th integer of the i-th line denotes Ai,jAi,j
    
    Then there are NN lines and each line has NN integers, the j-th integer of the i-th line denotes Bi,jBi,j
    
    1≤N≤2001≤N≤200, Ai,j,Bi,j∈{0,1}Ai,j,Bi,j∈{0,1}
    

    输出描述:

    Output the answer module 998244353998244353.
    

    示例1

    输入

    复制

    2
    0 1
    1 1
    1 0
    0 1
    

    输出

    复制

    2
    

    示例2

    输入

    复制

    3
    1 0 0
    0 1 0
    0 0 1
    1 1 1
    1 1 1
    1 1 1
    

    输出

    复制

    512
    

    示例3

    输入

    复制

    4
    0 1 0 1
    0 1 1 0
    0 1 1 1
    1 0 0 1
    1 0 1 1
    0 1 1 1
    1 0 0 1
    1 1 1 0
    

    输出

    复制

    8
    

    比赛的时候没学线代相关的算法,现在看的话其实还是挺套路的2333

    首先不难写出每个(c_{ij})要满足的等式:

    (Sigma_{i = 1}^{n}A_{ik}C_{kj} = B_{ij}C_{ij}),同时注意到这个加法是在模2意义下的加法,因此其本质就是异或运算,那么这个等式可以写为:

    (igoplus_{i = 1}^{n}A_{ik}C_{kj} = B_{ij}C_{ij})。右边那一项含有要求的变元,同时(C_{ij})正好也在左式,因此要把它移到左边。在左式中与(B_{ij}C_{ij})对应的实际上是(A_{ii}C_{ij}),所以如果(A_{ii} == B_{ij}),那么移项后(C_{ij})的系数实际上就是0了(两边同时异或上(A_{ii}C_{ij}));同理如果(A_{ii} != B_{ij}),那么移项后(C_{ij})的系数实际上就是1。

    矩阵C是列独立的,这样,我们取C矩阵的某一列(设为(C_{i}))作为列向量与A相乘:(A imes C_{i} = B_{i}⊙C_{i}),再移项实际上就是n个异或方程组,解出来的自由元的个数就是C的这一列能任意取值(0或1)的位置的个数,这样对于C的每一列都求出来自由元的个数,最终能够得到自由元的总数x,输出的答案就是(2^x)

    求解异或方程组可以用bitset优化的高斯消元来做。

    #include <bits/stdc++.h>
    #define mod 998244353
    #define int long long
    using namespace std;
    int n, a[205][205], b[205][205], m[205][205];
    long long fpow(long long a, long long b) {
    	long long ans = 1; 
    	for(; b; b >>= 1) {
    		if(b & 1) ans = ans * a % mod;
    		a = a * a % mod;
    	}
    	return ans % mod;
    }
    bitset<220> M[205];
    int Free;
    int guass(int n, int m)//n row n 行 m col m 列
    {
    	Free = 0;
        int row = 0, col = 0, maxx;
        for(; col < m; ++ col) {
            for(maxx = row; maxx < n; ++ maxx)
                if(M[maxx][col])
                    break;
            if(maxx == n) continue;
                    
            if(M[maxx][col] == 0) continue;
            
            swap(M[maxx], M[row]);
            
            for(int i = row + 1; i < n; ++ i) 
                if(M[i][col]) //如果这一列有数的话那一行全部消掉
                    M[i] = M[i] ^ M[row];
            row ++ ;
        }
        Free = n - row;
        if(row < n) {
        	
            for(int i = row; i < n; ++ i) 
                if(M[i][m])//矛盾,出现非零的常数项等于0,说明无解
                    return 2;
            return 1;//有无穷多组解
        }
        //行最简形矩阵,第i行第i列的表示的未知量x_i的一个解
        for(int i = n - 1; i >= 0; -- i) {//第i行,第i行第i列
            for(int j = i + 1; j < m; ++ j)//第j列,右边所有列都要消
                    M[i][m] = M[i][m] ^ (M[j][m] * M[i][j]);
        }
        return 0;
    }
    signed main() {
    	ios::sync_with_stdio(false);
    	cin >> n;
    	for(int i = 1; i <= n; i++) {
    		for(int j = 1; j <= n; j++) {
    			cin >> a[i][j];
    		}
    	}
    	for(int i = 1; i <= n; i++) {
    		for(int j = 1; j <= n; j++) {
    			cin >> b[i][j];
    		}
    	}
    	long long ans = 1, num = 0;
    	for(int j = 1; j <= n; j++) {//求c1j  c2j  ... cnj中的自由元个数
    		for(int i = 1; i <= n; i++) {
    			for(int k = 1; k <= n; k++) {
    				m[i][k] = a[i][k];
    			}
    			if(b[i][j] == a[i][i]) {
    				m[i][i] = 0;//相当于移项
    			} else {
    				//b[i][j]为0的话不影响
    				m[i][i] = 1;
    			}
    		}
    		//此时对m矩阵进行高斯消元解异或方程组,求自由元个数
    		//cout << endl << endl;
    		for(int ii = 1; ii <= n; ii++) {
    			for(int jj = 1; jj <= n; jj++) {
    				M[ii - 1][jj - 1] = m[ii][jj];
    			}
    		}
    		int result = guass(n, n);
    		if(result == 2) {
    			cout << 0;
    			return 0;
    		}
    		num += Free;
    		Free = 0;
    	}
    	ans = fpow(2, num);
    	cout << ans;
    	return 0;
    }
    
  • 相关阅读:
    Java中Timer的用法
    Java ThreadFactory接口用法
    ThreadPoolExecutor使用介绍
    linux命令学习-4-lsof
    备份文件-域名+日期扫描
    Trickbot展示新技巧:密码抓取器模块
    Trickbot增加的远程应用程序凭证抓取功能
    基于ATT和CK™框架的开放式方法评估网络安全产品
    调试键盘纪录类型的样本
    LordPE修复从进程dump出来的内存文件
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/14999979.html
Copyright © 2011-2022 走看看