N 個開關,操作某開關會翻轉其關聯開關狀態。給定初始狀態與目標狀態,求達到目標的操作方案數 (不計順序),每開關最多操作一次。本質是模 2 線性方程組求解,自由度即為方案數的 2 次冪。
a[i][j]:前 N 列為係數,第 N+1 列為常數項。#include <iostream>
#include <cstring>
using namespace std;
int a[32][32], n;
int gauss() {
int i = 0, j = 0, k, r, u;
while (i < n && j < n) {
r = i;
for (k = i; k < n; k++) if (a[k][j]) { r = k; break; }
if (a[r][j]) {
if (r != i) for (k = 0; k <= n; k++) swap(a[r][k], a[i][k]);
for (u = i+1; u < n; u++)
if (a[u][j])
for (k = i; k <= n; k++) a[u][k] ^= a[i][k];
i++;
}
j++;
}
for (u = i; u < n; u++) if (a[u][n]) return -1; // 無解
return 1 << (n - i); // 2^(自由變量數)
}
int main() {
int T; cin >> T;
while (T--) {
memset(a, 0, sizeof(a));
cin >> n;
for (int i = 0; i < n; i++) cin >> a[i][n]; // 初始狀態
for (int i = 0; i < n; i++) {
int x; cin >> x;
a[i][i] = 1;
a[i][n] ^= x; // 常數項 = 初始 ⊕ 目標
}
int x, y;
while (cin >> x >> y) {
if (x == 0 && y == 0) break;
a[y-1][x-1] = 1; // 操作 x 影響 y
}
int ans = gauss();
if (ans == -1) cout << "Oh,it's impossible~!!" << endl;
else cout << ans << endl;
}
return 0;
}