如题,以下是本帖讨论涉及到的部分代码:
#define rep(x, y, z) for(int x = (y); x <= (z); ++x)
rep(i, 1, n) {
int k = 0;
rep(j, i, n) if(a[j].test(i)) {k = j; break;}
swap(a[i], a[k]);
rep(j, 1, n) if(i != j && a[j].test(i)) a[j] ^= a[i];
}
rep(i, 1, n) ans[i] = a[i].test(n + 1);
代码中 a 是一个 n×(n+1) 的矩阵(使用 bitset 数组实现),保证异或方程组有解,但不保证解唯一。在程序结束时,我期望 ans 中保存了一组异或方程组的解。
在本题中,我试图使用以上方式求解,但因为没有写第四行的 break 一直 WA on 51,后来加上了就直接过了。我尝试在高斯消元开始前 shuffle 矩阵的每一行,结果 WA 得更靠前。我在 CF 上对洛谷仅有的一篇题解进行了同样的尝试,与我的代码结果相同。本题之前也有 讨论 遇到了和我一样的问题,但没有得到解答。
我尝试在本地进行对拍,拍出一组上述 AC 代码的 hack 数据,但是一直拍不出来。与之对比,所有提交后 WA 了的代码都在一分钟内拍出了错误。
我有如下几点疑问:
- 为什么在进行高斯消元前打乱了矩阵的每一行,就会得到错误的结果?
- 注意到不满秩时会执行交换一行与第 0 行的操作,于是我基于 AC 代码,在每一轮高斯消元后将第 0 行填充为随机数,但是依然拍不出错误。这个操作到底会导致什么后果?
- 或者难道是因为这种构造解的方式是错误的,只是因为本题的矩阵的特殊性质歪打正着?那正确的方法应该是什么样的?(本题的矩阵的特殊性质包括关于主对角线对称、n×n 的矩阵中每行每列 1 的个数均为偶数、主对角线上元素与对应行的第 n+1 列元素相同)