题意:n个状态会改变的灯。每个灯都有一些与之关联的灯,当某个灯状态变化时,与之相关联的灯状态也会改变。给出灯的初始状态和末状态。问能有几种方式到达末状态。
思路:(x1,x2...xn)=>(y1,y2...yn) 每个灯的状态转化:.x1 xor a[0][0] * b1 xor a[0][1] *b2 xor ... xor a[0][n-1] = y1.两边同时异或x1
求出矩阵的秩。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn =30;
int a[30][30];
int a1[30],b1[30];
void print(int n)
{
for(int i=0;i<n;i++)
{
for(int j=0;j<=n;j++)
printf("%d ",a[i][j]);
printf("\n");
}
printf("\n");
}
int Gauss(int equ,int var)
{
int maxrow;
int row=0,col=0,num=0;
for(;row<equ&&col<var;row++,col++)//
{
maxrow=row;
for(int k=row+1;k<equ;k++)
if(abs(a[k][col])>abs(a[maxrow][col]))maxrow=k;
if(maxrow!=row)
{
for(int j=row;j<=var;j++)//
swap(a[maxrow][j],a[row][j]);
}
if(a[row][col]==0)
{
row--;
continue;
}
for(int i=row+1;i<equ;i++)
{
if(a[i][col]!=0)
{
for(int j=0;j<=var;j++)
a[i][j]=a[i][j]^a[row][j];
}
}
}
for(int i=row;i<equ;i++)
if(a[i][col]!=0)return -1;
return 1<<(var-row);
}
int main()
{
int t;
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
memset(a,0,sizeof(a));
for(int i=0;i<n;i++)
scanf("%d",&a1[i]);
for(int i=0;i<n;i++)
scanf("%d",&b1[i]);
for(int i=0;i<n;i++)
a[i][n]=a1[i]^b1[i];
for(int i=0;i<n;i++)
a[i][i]=1;
int s,t;
while(scanf("%d%d",&s,&t)&&(s+t))
{
a[t-1][s-1]=1;//
}
int ans=Gauss(n,n);
if(ans==-1)printf("Oh,it's impossible~!!\n");
else printf("%d\n",ans);
}
}