POJ1830 开关问题
思路
本题同样也是异或方程组的题目,但是不同的是需要求出方案数,即要求出解的个数
由线性代数的知识,方程的自由元数决定了解的个数
由于异或是在模2条件下的加法运算,所以解的个数是2的自由元个数次方
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int _mat[31][31],ans;
int Gauss(int n){
for(int i=1;i<=n;i++){
bool f=true;
if(_mat[i][i]==0){
f=false;
for(int j=i+1;j<=n;j++){
if(_mat[j][i]==1){
for(int k=1;k<=n+1;k++)
swap(_mat[j][k],_mat[i][k]);
f=true;
break;
}
}
}
if(f){
for(int j=1;j<=n;j++)
if(i!=j&&_mat[j][i]==1){
for(int k=1;k<=n+1;k++)
_mat[j][k]^=_mat[i][k];
}
}
}
for(int i=1;i<=n;i++){
bool tmp=true;
for(int j=1;j<=n;j++){
if(_mat[i][j]!=0)
tmp=false;
}
if(tmp){
if(_mat[i][n+1])
return 0;
else
ans<<=1;
}
}
return 1;
}
int n,A[100],B[100];
void work(){
memset(_mat,0,sizeof(_mat));
ans=1;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&A[i]);
}
for(int i=1;i<=n;i++){
scanf("%d",&B[i]);
_mat[i][n+1]=A[i]^B[i];
_mat[i][i]=1;
}
int i,j;
scanf("%d %d",&i,&j);
while(!(i==0&&j==0)){
_mat[j][i]=1;
scanf("%d %d",&i,&j);
}
int rev=Gauss(n);
if(!rev){
printf("Oh,it's impossible~!!\n");
}
else{
printf("%d\n",ans);
}
}
int main(){
int T;
scanf("%d",&T);
while(T--){
work();
}
return 0;
}