A Matrix Equation
题意:
求有多少个C可以满足
A
×
C
=
B
⋅
C
A\times C=B\cdot C
A×C=B⋅C
思路:
高斯消元
根据线代叉乘的规律,拆成对于C的每一列求解。
一个性质是mod2下的加法就是异或。
于是就变成了一个高斯消元异或方程组求解,对于C的每一列答案就是 2 自 由 元 个 数 2^{自由元个数} 2自由元个数,所有列直接根据乘法原理相乘。
n的数据是200,时间复杂度是 O ( n 4 ) O(n^4) O(n4),练习的时候直接交就过去了。
赛后学到一个优化:可以用bitset,bitset可以看作bool数组,但优化了空间复杂度和时间复杂度,并且可以像整形一样按位与或。
赋值
bitset重载了[]运算符,故可以像bool数组那样赋值
bi[2] = 1;
这样就能将第二位赋值为1
常用函数
b1 = b2 & b3;//按位与
b1 = b2 | b3;//按位或
b1 = b2 ^ b3;//按位异或
b1 = ~b2;//按位补
b1 = b2 << 3;//移位
int one = b1.count();//统计1的个数
优化作用
常常碰到处理的数组只有0和1的变化,此时就可以使用bitset优化。比如求两个集合的交集可以使用按位与运算,求并集可以使用按位或运算
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 200 + 5;
const int mod = 998244353;
typedef long long ll;
typedef int itn;
ll qpow(ll a,ll b,ll m){
ll res = 1;
while(b){
if(b & 1) res = res * a % mod;
a = a * a % m;
b >>= 1;
}
return res % m;
}
bitset<maxn> a[maxn];
int A[maxn][maxn],B[maxn][maxn];
ll guass(int n,int m)
{
int row = 0,col = 0,maxx;
for(; col < m && row < n ;++ col){
for(maxx = row ;maxx < n;++maxx){
if(a[maxx][col])
break;
}
if(a[maxx][col] == 0)
continue;
swap(a[maxx],a[row]);
for(int i = row + 1;i < n; ++i){
if(a[i][col])
a[i] ^= a[row];
}
row++;
}
return qpow(2,n - row,mod);
}
int main()
{
int n;
cin>>n;
ll ans = 1;
for(int i =0;i < n; ++i)
for(int j = 0;j < n; ++j)
cin>>A[i][j];
for(int i = 0;i < n; ++i)
for(int j = 0;j< n ; ++j)
cin>>B[i][j];
for(int j = 0;j < n; ++j){
for(int i = 0;i < n; ++i)
for(int k = 0;k < n; ++k)
a[i][k] = A[i][k];
for(int i =0;i < n; ++i)
a[i][i] = (A[i][i] ^ B[i][j]);
ll tem = guass(n,n);
ans = ans * tem % mod;
}
cout<<ans<<endl;
return 0;
}