第 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
首先不难写出每个要满足的等式:
,同时注意到这个加法是在模2意义下的加法,因此其本质就是异或运算,那么这个等式可以写为:
。右边那一项含有要求的变元,同时正好也在左式,因此要把它移到左边。在左式中与对应的实际上是,所以如果,那么移项后的系数实际上就是0了(两边同时异或上);同理如果,那么移项后的系数实际上就是1。
矩阵C是列独立的,这样,我们取C矩阵的某一列(设为作为列向量与A相乘:,再移项实际上就是n个异或方程组,解出来的自由元的个数就是C的这一列能任意取值(0或1)的位置的个数,这样对于C的每一列都求出来自由元的个数,最终能够得到自由元的总数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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
2020-07-11 QT入门-QMainWindow类
2020-07-11 洛谷P1967 货车运输 (最大生成树+树链剖分)
2020-07-11 洛谷P3384 【模板】轻重链剖分
2020-07-11 洛谷P5661 公交换乘(二分)
2020-07-11 洛谷P4047 [JSOI2010]部落划分(最小生成树)