P7693 题解
这道题缺少 Special Judge,害得我调了一上午然后发现是没有 Special Judge 的问题
思路
首先可以以
相当于对于每个
然而,多个变量的同余方程组求解并不容易。考虑到相加后对
考虑如何对这样的方程组进行消元。类比高斯消元,处理到第
显然,等号两边同时异或上某个数时,等式仍然成立。因此,对于某个我们希望消去
代码实现时,这可以转化为将系数和等号右侧的值都与某行异或。最后统计答案时的方法和高斯消元一致。
注意不要把高斯消元写错。
代码
#include <bits/stdc++.h>
using namespace std;
inline void train() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
}
#ifndef ONLINE_JUDGE
#define ONLINE_JUDGE
#endif
constexpr int N = 800, NT = 1504;
int n, mat[N][N], got[N];
bitset<N> gen;
bool vis[N];
inline void swap_mat(int a, int b) {
if (a == b) return;
for (int i = 1; i <= n+1; i++) {
int tmp = mat[a][i];
mat[a][i] = mat[b][i];
mat[b][i] = tmp;
}
}
inline void xor_mat(int target, int source) {
if (target == source) return;
for (int i = 1; i <= n+1; i++) {
mat[target][i] ^= mat[source][i];
}
}
int main() {
train();
cin>>n;
for (int i = 0; i < n; i++) {
int x;
cin>>x;
if (x) gen.set(i);
}
for (int i = 0; i < n; i++) {
int x;
cin>>x;
for (int j = n-1, mpos = 1; j >= 0; j--, mpos++) {
if (gen.test(j)) mat[i+1][mpos] = 1;
}
if (x) mat[i+1][n+1] = 1;
gen >>= 1;
if (x) gen.set(n-1); // Top position
}
for (int i = 1; i <= n; i++) {
int foundrow = -1;
for (int j = 1; j <= n; j++) {
if (mat[j][i] && (!vis[j])) {
foundrow = j;
break;
}
}
if (foundrow < 0) continue;
swap_mat(i, foundrow);
vis[i] = true;
for (int j = 1; j <= n; j++) {
if (vis[j]) continue;
if (mat[j][i]) {
xor_mat(j, i);
}
}
}
for (int i = n; i >= 1; i--) {
int right = mat[i][n+1];
for (int j = i+1; j <= n; j++) {
right ^= got[j] & mat[i][j];
}
if (mat[i][i] == 0) {
if (right == 1) {
cout<<"-1"<<endl;
return 0;
} else {
// got[i] = 1; // 加不加都可以,没有 spj 时分数不同
}
} else {
got[i] = right;
}
}
for (int i = 1; i <= n; i++) cout<<got[i]<<' ';
cout<<endl;
return 0;
}