题目来源:第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(济南)A
题目链接:A-Matrix Equation
题意
定义01矩阵的两种运算:对于大小为 \(N \times N\) 的01矩阵 \(X\)、\(Y\),记 \(Z = X \times Y\),\(D = X \odot Y\),则有 \(Z_{i,j} = (\sum_{k=1}^{N}X_{i,k}Y_{k,j})\ mod\ 2\),\(D_{i,j} = X_{i,j}Y_{i,j}\).
对于给定的两个 \(N \times N\) 的01矩阵 \(A\)、\(B\),求有多少个 \(N \times N\) 的01矩阵 \(C\),满足 \(A \times C = B \odot C\),答案对 \(998244353\) 取模。
数据范围:\(1 \le N \le 200\),\(A_{i,j},B_{i,j} \in \{0,1\}\).
思路:高斯消元 + bitset优化
根据条件限制,可以得到 \(N \times N\) 个 含有 \(N \times N\) 个未知量的方程,未知量就是矩阵 \(C\) 的所有元素。
对方程组进行求解,每一个未知量要么是确定的值,要么是自由未知量,取值任意(可以任取 \(0/1\))。因此,若记自由未知量的个数为 \(cnt\),答案就是 \(\large 2^{cnt}\).
但是直接进行高斯消元的话,复杂度是 \(O(n^6)\),是无法接受的,需要进行优化。
观察限制条件的左右式子,可以发现,\(C\) 的不同列是相互独立的,因此可以考虑对 \(C\) 的每一列进行高斯消元,复杂度为 \(O(n·n^3)\) ,即\(O(n^4)\).
又因为矩阵元素的值只有 \(0\)、\(1\),因此可以用bitset进行优化,复杂度降为 \(O(n·{\large \frac{n^3}{\omega}})\),即 \(O({\large \frac{n^4}{\omega}})\),其中 \(\omega = 32\ or\ 64\),与机器有关。
代码
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int N = 210;
const int mod = 998244353;
int n, A[N][N], B[N][N];
bitset<N> b[N];
int gauss()
{
int c, r;
for(c = 1, r = 1; c <= n; ++ c) {
int t = r;
for(int i = r; i <= n && !b[t][c]; ++ i) t = i;
if(!b[t][c]) continue;
swap(b[r], b[t]);
for(int i = r + 1; i <= n; ++ i) {
if(b[i][c]) b[i] ^= b[r];
}
++ r;
}
return n + 1 - r;
}
int qmi(int m, int k, int p)
{
int res = 1;
while(k) {
if(k & 1) res = (LL)res * m % p;
m = (LL)m * m % p;
k >>= 1;
}
return res;
}
int main()
{
cin.tie(0);
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];
}
int cnt = 0;
for(int j = 1; j <= n; ++ j) {
for(int i = 1; i <= n; ++ i) b[i].reset();
for(int i = 1; i <= n; ++ i) {
for(int k = 1; k <= n; ++ k) b[i][k] = A[i][k];
b[i][i] = b[i][i] ^ B[i][j];
}
cnt += gauss();
}
cout << qmi(2, cnt, mod) << endl;
return 0;
}
标签:01,int,45,矩阵,times,程序设计,未知量,高斯消
From: https://www.cnblogs.com/jakon/p/16867933.html