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;
}
posted @ 2021-01-28 23:56  dreagonm  阅读(77)  评论(0编辑  收藏  举报