2020ICPC济南 A Matrix Equation(高斯消元、自由元数量)

链接

题目描述

We call a matrix “01 Square” if and only if it’s a N × N N\times N N×N matrix and its elements are all 0 0 0 or 1 1 1.

For two 01 Squares X X X, Y Y Y, we define two operators X × Y X\times Y X×Y and X ⊙ Y X\odot Y XY. The value of them are also 01 Square matrices and calculated below(we use Z Z Z to abbreviate X × Y X\times Y X×Y and D D D to abbreviate X ⊙ Y X\odot Y XY):

Z i , j = ( ∑ k = 1 N X i , k Y k , j )   m o d   2 Z_{i,j}=(\sum_{k=1}^{N}X_{i,k}Y_{k,j})~mod~2 Zi,j=(k=1NXi,kYk,j) mod 2

D i , j = X i , j Y i , j D_{i,j}=X_{i,j}Y_{i,j} Di,j=Xi,jYi,j

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

A × C = B ⊙ C A\times C=B\odot C A×C=BC

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

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

输入描述:

The first line has one integer N N N

Then there are N N N lines and each line has N N N integers, the j-th integer of the i-th line denotes A i , j A_{i,j} Ai,j

Then there are N N N lines and each line has N N N integers, the j-th integer of the i-th line denotes B i , j B_{i,j} Bi,j

1 ≤ N ≤ 200 1\leq N\leq 200 1N200, A i , j , B i , j ∈ { 0 , 1 } A_{i,j},B_{i,j} \in \{0,1\} Ai,j,Bi,j{0,1}

输出描述:

Output the answer module 998244353 998244353 998244353.

输入

2
0 1
1 1
1 0
0 1

输出

2

输入

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

输出

512

输入

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

思路

设矩阵 A A A B B B 分别如下:

A = [ 1 0 1 1 0 0 0 1 1 ] , B = [ 1 0 1 1 0 0 0 1 1 ] A=\begin{bmatrix} 1&0&1\\ 1&0&0\\ 0&1&1\\ \end{bmatrix}, B=\begin{bmatrix} 1&0&1\\ 1&0&0\\ 0&1&1\\ \end{bmatrix} A=110001101,B=110001101

设矩阵 C C C
C = [ a d g b e h c f i ] C=\begin{bmatrix} a&d&g\\ b&e&h\\ c&f&i\\ \end{bmatrix} C=abcdefghi

由题意有: A × C = B ⊙ C A\times C=B\odot C A×C=BC

首先解 C C C 第一列的三个变量: a , b , c a,b,c a,b,c。有如下关系:

{ a + c ≡ 0 a + b ≡ 0 b + c ≡ 0 \left\{ \begin{aligned} a+c\equiv0 \\ a+b\equiv0 \\ b+c\equiv0 \\ \end{aligned} \right. a+c0a+b0b+c0
相当于得到如下增广矩阵:
[ 1 0 1 0 1 1 0 0 0 1 1 0 ] \begin{bmatrix} 1&0&1&0\\ 1&1&0&0\\ 0&1&1&0\\ \end{bmatrix} 110011101000

用高斯消元法解得:
[ 1 0 1 0 0 1 1 0 0 0 0 0 ] \begin{bmatrix} 1&0&1&0\\ 0&1&1&0\\ 0&0&0&0\\ \end{bmatrix} 100010110000

这一列有一个自由元。用同样的方法,计算出 n n n 列自由元数量之和 c n t cnt cnt,那么答案就是 2 c n t 2^{cnt} 2cnt

注意

  1. 高斯消元过程中始终要进行模 2 2 2 计算。
  2. 如果使用 % \% % 运算符,可能会被卡常,使用异或运算来优化。
#include
#define ll long long
using namespace std;
const int N=210,mod=998244353;
int x[N][N],y[N][N],a[N][N],ans,n;

ll qpow(ll a,ll b){
	ll ret=1;
	while(b){
		if(b&1LL) ret=ret*a%mod;
		a=a*a%mod; b>>=1LL;
	}
	return ret;
}

void gauss(){
	int ri=1,add=0;
	for(int i=1;i<=n;i++){
		if(add) ri++; add=1;
		int mx=ri;
		for(int j=ri+1;j<=n;j++)
			if(a[j][i]>a[mx][i]) mx=j;
		if(a[mx][i]==0){ ans++,add=0; continue; }
		for(int j=i;j<=n+1;j++) swap(a[ri][j],a[mx][j]);
		for(int k=1;k<=n;k++) if(ri!=k&&a[k][i]!=0)
			for(int j=n+1;j>=i;j--) a[k][j]^=a[ri][j];
	}
}

signed main(){
	cin>>n;
	for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) cin>>x[i][j];
	for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) cin>>y[i][j];
	for(int i=1;i<=n;i++){
		memcpy(a,x,sizeof(x));
		for(int j=1;j<=n;j++)
			if(y[j][i]==1) a[j][j]^=1;
		gauss();
	}
	cout<<qpow(2,ans)<<"\n";
}

你可能感兴趣的:(数学,算法,线性代数)