先令(0/1)表示开关的状态(关/开),那么(按/不按)开关表示为(1/0)
然后就像高斯消元一样,把每一个开关和他相关的开关列出一条式子(n个开关一共就n条),然后把他们变成阶梯形矩阵,从后往前求解。
然后分情况讨论:
1:系数全部为0,但是结果为1,那么无解
2:系数有1,那么该开关的状态肯定是确定的,跳过
3:系数全部为0,结果也为0,那么按不按都可以
讨论完以后向上删除。
做完以后我才发现是可以用一个int来储存一条式子的状态的。。。
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 41;
int n;
int a[N], b[N], c[N][N];
int main() {
int T; cin >> T;
while (T--) {
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 1; i <= n; i++) cin >> b[i];
int x, y;
memset(c, 0, sizeof(c));
while (~scanf("%d%d", &x, &y) && x && y) c[y][x] = 1;
for (int i = 1; i <= n; i++) c[i][n + 1] = a[i] ^ b[i], c[i][i] = 1;
for (int ki = 1; ki < n; ki++) {
int k = ki;
for(; k <= n && !c[k][ki]; k++);
if (k == n + 1) continue;
if (k != ki) for (int i = 1; i <= n + 1; i++) swap(c[ki][i], c[k][i]);
for (int i = ki + 1; i <= n; i++) {
if (c[i][ki] == 0) continue;
for (int j = ki; j <= n + 1; j++)
c[i][j] = c[i][j] ^ c[ki][j];
}
}
bool flag = 1;
int sum = 0;
for (int i = n; i >= 1; i--) {
bool bk = 0;
for (int j = i; j <= n; j++)
if (c[i][j] == 1) { bk = 1; continue;}
if (!bk) {
if (c[i][n + 1] == 1) {flag = 0; break; }
sum++;
}
if (c[i][i] == 0) continue;
for (int j = i - 1; j >= 1; j--) {
if (c[j][i] == 0) continue;
for (int k = i; k <= n + 1; k++)
c[j][k] = c[j][k] ^ c[i][k];
}
}
if (!flag) {puts("Oh,it's impossible~!!"); continue;}
int ans = 1;
for (int i = 1; i <= sum; i++) ans = ans * 2;
cout << ans << endl;
}
return 0;
}
%%%