题意
传送门 POJ 1830
题解
设灯
i
i
i 是否开关为
x
i
x_i
xi,灯
j
j
j 操作时是否会影响到灯
i
i
i 为
a
i
,
j
a_{i,j}
ai,j,设灯
i
i
i 初始与结束的开关状态分别为
s
i
,
t
i
s_i,t_i
si,ti,则灯
i
i
i 满足
X
O
R
j
∈
[
1
,
N
]
(
x
j
&
a
i
,
j
)
=
s
i
⊕
t
i
XOR_{j\in [1,N]}(x_j\ \&\ a_{i,j})=s_i\oplus t_i
XORj∈[1,N](xj & ai,j)=si⊕ti 联立异或线性方程组,高斯消元求解,实现上将代表灯
i
i
i 状态的方程,即增广矩阵的每一行进行状态压缩,此时高斯消元的复杂度为
O
(
N
2
)
O(N^2)
O(N2)。
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
using namespace std;
#define maxn 30
int N, A[maxn], S[maxn], T[maxn];
int gauss_jordan()
{
for (int i = 1; i <= N; ++i)
{
for (int j = i + 1; j <= N; ++j)
if (A[i] < A[j])
swap(A[i], A[j]);
if (A[i] == 0)
return 1 << (N - i + 1);
if (A[i] == 1)
return 0;
for (int j = N; j >= 1; --j)
if (A[i] >> j & 1)
{
for (int k = 1; k <= N; ++k)
if (i != k && (A[k] >> j & 1))
A[k] ^= A[i];
break;
}
}
return 1;
}
int main()
{
int t;
scanf("%d", &t);
while (t--)
{
memset(A, 0, sizeof(A));
scanf("%d", &N);
for (int i = 1; i <= N; ++i)
scanf("%d", S + i);
for (int i = 1; i <= N; ++i)
scanf("%d", T + i);
for (int i = 1; i <= N; ++i)
A[i] |= 1 << i, A[i] |= S[i] ^ T[i];
int x, y;
while (~scanf("%d%d", &x, &y) && (x | y))
A[y] |= 1 << x;
int res = gauss_jordan();
if (!res)
puts("Oh,it's impossible~!!");
else
printf("%d\n", res);
}
return 0;
}