AcWing 208. 开关问题
原题链接
中等
作者:
皓首不倦
,
2020-09-16 17:13:50
,
所有人可见
,
阅读 623
'''
转成异或方程组求解,每个解数值为0表示开关没有动过,1表示开关拨动过一次
假设最后自由元数量是k,就有2^k种不同方案
'''
case_num = int(input())
for _ in range(case_num):
n = int(input())
start_stat = list(map(int, input().split()))
end_stat = list(map(int, input().split()))
m = [[0] * (n+1) for _ in range(n)]
for i in range(n):
m[i][i] = 1
while True:
a, b = map(int, input().split())
if a == 0 and b == 0:
break
a, b = a-1, b-1
m[b][a] = 1
for i in range(n):
m[i][n] = start_stat[i] ^ end_stat[i]
# 高斯消元
for col in range(0, n):
max_val, max_row = m[col][col], col
for row in range(col + 1, n):
if max_val == 1:
break
if m[row][col] > max_val:
max_val, max_row = m[row][col], row
break
if max_val == 0:
continue
m[col], m[max_row] = m[max_row], m[col]
for row in range(col + 1, n):
if m[row][col] == 0:
continue
for j in range(col, n + 1):
m[row][j] ^= m[col][j]
flag = 0
ans = [0] * n
solution_cnt = 1
for i in range(n - 1, -1, -1):
val = m[i][n]
s = 0
for j in range(n - 1, i, -1):
if m[i][j] == 1:
s ^= ans[j]
val ^= s
if val == 0 and m[i][i] == 0:
# 多组解
flag = 1
solution_cnt *= 2
if val == 1 and m[i][i] == 0:
# 无解
flag = 2
break
else:
ans[i] = val
if flag == 2:
print("Oh,it's impossible~!!")
else:
print(solution_cnt)