第45届ICPC济南站A题 Matrix Equation(高斯消元)

传送门

题意

给两个 \(n\times n\)\(01\) 矩阵 \(A,B\),问有多少种 \(01\) 矩阵 \(C\) 满足 \(A\times C=B\cdot C\)

题解

\(A\times C=B\cdot C\) 打开,得:

\[A_{1,1}\cdot C_{1,1}+A_{1,2}\cdot C_{2,1}+...+A_{1,n}\cdot C_{n,1}=B_{1,1}\cdot C_{1,1} \\ A_{1,1}\cdot C_{1,2}+A_{1,2}\cdot C_{2,2}+...+A_{1,n}\cdot C_{n,2}=B_{1,2}\cdot C_{1,2} \\ ... \\ A_{n,1}\cdot C_{1,n}+A_{n,2}\cdot C_{2,n}+...+A_{n,n}\cdot C_{n,n}=B_{n,n}\cdot C_{n,n} \\ \]

按理来说找到这个 \(n^2\) 的线性方程组中自由元的个数 \(x\) 就能得出答案 \(2^x\) 了,但是复杂度不允许。再观察可以发现,对于每一列的未知数 \(C_{1,i},C_{2,i},...,C_{n,i}\) 可以形成一组独立的线性方程组,与其他列互不干扰:

\[A_{1,1}\cdot C_{1,i}+A_{1,2}\cdot C_{2,i}+...+A_{1,n}\cdot C_{n,i}=B_{1,i}\cdot C_{1,i} \\ A_{2,1}\cdot C_{1,i}+A_{2,2}\cdot C_{2,i}+...+A_{2,n}\cdot C_{n,i}=B_{2,i}\cdot C_{2,i} \\ ... \\ A_{n,1}\cdot C_{1,i}+A_{n,2}\cdot C_{2,i}+...+A_{n,n}\cdot C_{n,i}=B_{n,i}\cdot C_{n,i} \\ \]

那么可以对于每一列列出系数矩阵,求自由元个数 \(x_i\),最终答案即为 \(2^{x_1+x_2+...+x_n}\)

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=210;
const int mod=998244353;
int n,a[N][N],b[N][N];
bitset<N> m[N];

LL qpow(LL x,LL k){
	LL res=1;
	while(k){
		if(k&1) res=res*x%mod;
		x=x*x%mod;
		k>>=1;
	}
	return res;
}

int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&a[i][j]);
	for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&b[i][j]);
	LL ans=1;
	for(int w=1;w<=n;w++){
		for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) m[i][j]=a[i][j];
		for(int i=1;i<=n;i++) m[i][i]=m[i][i]^b[i][w];
		for(int i=1,pos=1;pos<=n;i++){
			while(pos<=n) {
				for(int j=i+1;j<=n;j++) if(m[j][pos]) swap(m[j],m[i]);
				if(m[i][pos]) break;
				pos++;
			}
			if(pos>n) {ans=ans*qpow(2,n-i+1)%mod;break;}
			for(int j=i+1;j<=n;j++)
				if(m[j][pos]) m[j]^=m[i];
		}
	}
	printf("%lld\n",ans);
	return 0;
} 
posted @ 2021-03-13 16:43  BakaCirno  阅读(128)  评论(0编辑  收藏  举报