题目:POJ1830.
题目大意:给定一个长度为为
n
n
n的初始
01
01
01序列
a
a
a,要求你把序列操作(给一些位置取反)成一个给定的
01
01
01序列.给出一些关系
i
 
j
i\,j
ij,表示若
i
i
i被操作则
j
j
j也要被操作.
1
≤
n
<
29
1\leq n< 29
1≤n<29.
设每一个开关的初始状态为
b
i
b_i
bi,结束状态
e
i
e_i
ei,
a
i
,
j
=
1
/
0
a_{i,j}=1/0
ai,j=1/0表示第
i
i
i个数会/不会被第
j
j
j个数影响,
x
i
x_i
xi表示第
i
i
i个点被操作几次.我们发现这个东西可以列成一个异或方程组:
{
a
1
,
1
x
1
 
x
o
r
 
a
1
,
2
x
2
 
x
o
r
 
⋯
 
x
o
r
 
a
1
,
n
x
=
b
1
 
x
o
r
 
e
1
a
2
,
1
x
1
 
x
o
r
 
a
2
,
2
x
2
 
x
o
r
 
⋯
 
x
o
r
 
a
2
,
n
x
=
b
2
 
x
o
r
 
e
2
⋮
a
n
,
1
x
1
 
x
o
r
 
a
n
,
2
x
2
 
x
o
r
 
⋯
 
x
o
r
 
a
n
,
n
x
=
b
n
 
x
o
r
 
e
n
\left\{\begin{matrix} a_{1,1}x_1\,xor\,a_{1,2}x_2\,xor\,\cdots\,xor\,a_{1,n}x=b_1\,xor\,e_1\\ a_{2,1}x_1\,xor\,a_{2,2}x_2\,xor\,\cdots\,xor\,a_{2,n}x=b_2\,xor\,e_2\\ \vdots\\ a_{n,1}x_1\,xor\,a_{n,2}x_2\,xor\,\cdots\,xor\,a_{n,n}x=b_n\,xor\,e_n \end{matrix}\right.
⎩⎪⎪⎪⎨⎪⎪⎪⎧a1,1x1xora1,2x2xor⋯xora1,nx=b1xore1a2,1x1xora2,2x2xor⋯xora2,nx=b2xore2⋮an,1x1xoran,2x2xor⋯xoran,nx=bnxoren
我们得到了一个异或方程组,发现异或方程组其实很容易解,把加减操作换成异或即可.而且我们发现这个方程中一行只有 30 30 30个 0 / 1 0/1 0/1,所以可以状态压缩.
代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define Abigail inline void
typedef long long LL;
const int N=29;
int a[N+9],n,ans;
int Gauss(int *a,int n){
for (int i=1;i<=n;++i){
for (int j=i+1;j<=n;++j)
if (a[j]>a[i]) swap(a[j],a[i]);
if (a[i]==0) return n-i+1;
if (a[i]==1) return -1;
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[i];
break;
}
}
return 0;
}
Abigail into(){
scanf("%d",&n);
int x,y;
for (int i=1;i<=n;++i)
scanf("%d",&a[i]);
for (int i=1;i<=n;++i){
scanf("%d",&x);
a[i]^=x;
}
while (~scanf("%d%d",&x,&y)&&x+y)
a[y]|=1<<x;
}
Abigail work(){
for (int i=1;i<=n;++i)
a[i]|=1<<i;
ans=Gauss(a,n);
}
Abigail outo(){
if (ans==-1) puts("Oh,it's impossible~!!");
else printf("%d\n",1<<ans);
}
int main(){
int T;
scanf("%d",&T);
while (T--){
into();
work();
outo();
}
return 0;
}