题目大意
给出 (n) 个开关,有很多对关系 (x,y) ,满足你改变 (x) 的状态 (y) 的状态也会改变。问从初始状态变为结束状态有多少种方案数(不考虑操作顺序)。
(nle 30)
思路
算是高斯消元一种比较奇妙的应用吧。
我们首先发现顺序是不影响答案的,然后对于一个开关就只有改变或者不改变两种选择,我们假设这个为 (x[i]),我们可以得到关系式:
[st[i]otimes(a[i][1] imes x[1]otimes a[i][2] imes x[2]otimes ... otimes a[i][n] imes x[n])=ed[i]
]
其中 (st[i],ed[i]) 分别表示初始状态和结束状态,(a[i][j]) 表示 (i) 是否随 (j) 变化而变化。
然后你发现我们如果对这个东西进行高斯消元,答案就是 (2) 的自由元个数。
时间复杂度 (Theta(n^3)) 。
( exttt{Code})
#define Int register int
#define MAXN 35
template <typename T> void read (T &x){x = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){x = x * 10 + c - '0';c = getchar();}x *= f;}
template <typename T,typename ... Args> void read (T &x,Args& ... args){read (x),read (args...);}
template <typename T> void write (T x){if (x < 0) putchar ('-'),x = -x;if (x > 9) write (x / 10);putchar (x % 10 + '0');}
int n,st[MAXN],ed[MAXN],mat[MAXN][MAXN];
int Gauss (){//输出自由元的个数
Int i = 1,col = 1;
for (;i <= n && col <= n;++ i,++ col){
int pos = i;
for (Int j = i + 1;j <= n;++ j) if (mat[j][col] > mat[pos][col]) pos = j;
if (i ^ pos) swap (mat[i],mat[pos]);
if (mat[i][col] == 0){
-- i;
continue;
}
for (Int j = i + 1;j <= n;++ j)
if (mat[j][col])
for (Int k = col;k <= n + 1;++ k) mat[j][k] ^= mat[i][k];
}
for (Int j = i;j <= n;++ j) if (mat[j][col]) return -1;
return n - i + 1;
}
signed main(){
int t;read (t);
while (t --){
read (n);
memset (mat,0,sizeof (mat));
for (Int i = 1;i <= n;++ i) read (st[i]),mat[i][i] = 1;
for (Int i = 1;i <= n;++ i) read (ed[i]),mat[i][n + 1] = ed[i] ^ st[i];
for (Int x,y;;){
read (x,y);
if (!x && !y) break;
else mat[y][x] = 1;
}
int get = Gauss ();
if (get == -1) puts ("Oh,it's impossible~!!");
else write (1 << get),putchar ('
');
}
return 0;
}