题目大意:
有N个开关,存在着某些联系,当变化一个开关后,与之相关的开关也会变化。
你的目标是经过若干次开关操作后使得最后N个开关达到一个特定的状态。对于任意一个开关,最多只能进行一次开关操作。
你的任务是,计算有多少种可以达到指定状态的方法。
(不计开关操作的顺序)
0 < N < 29
分析:
将能影响某个开关的所有开关罗列一下,
可以得到一个异或方程组,
可以通过异或高斯消元来解,
当存在
0=1
0
=
1
的情况时则无解
其他情况下,
因为自由元可以取
0或1
0
或
1
所以方程组的解为
2cnt
2
c
n
t
cnt
c
n
t
为自由元的数量
代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define N 105
using namespace std;
int a[N], T, n;
int main(){
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
for (int i = 1; i <= n; i++) {
int x;
scanf("%d", &x);
a[i] = a[i] ^ x;
a[i] = a[i] | (1 << i);
}
int x, y;
while (~scanf("%d %d", &x, &y)) {
if (!x && !y) break;
a[y] = a[y] | (1 << x);
}
int ans = 1;
for (int i = 1; i <= n; i++) {
for (int j = i + 1; j <= n; j++)
if (a[j] > a[i]) swap(a[i], a[j]);
if (!a[i]) {
ans = 1 << (n - i + 1);
break;
}
if (a[i] == 1) {
ans = 0;
break;
}
for (int k = n; k >= 1; k--)
if (a[i] >> k & 1) {
for (int j = 1; j <= n; j++)
if (i != j && (a[j] >> k & 1)) a[j] = a[j] ^ a[i];
break;
}
}
if (!ans) printf("Oh,it's impossible~!!\n");
else printf("%d\n", ans);
}
return 0;
}