POJ 1830 开关问题(高斯消元)

题目链接:http://poj.org/problem?id=1830

题意:有N个相同的开关,每个开关都与某些开关有着联系,每当你打开或者关闭某个开关的时候,其他的与此开关相关联的开关也会相应地发生变化,即这些相联系的开关的状态如果原来为开就变为关,如果为关就变为开。你的目标是经过若干次开关操作后使得最后N个开关达到一个特定的状态。对于任意一个开关,最多只能进行一次开关操作。你的任务是,计算有多少种可以达到指定状态的方法。(不计开关操作的顺序)

思路:建立矩阵。求解。无解的情况是有一个方程的值为1,但是系数全部为0;若有解,设系数和值全部为0的方程为X,则答案为2^X。

 

int S[N],T[N];

int a[N][N],n;



void build()

{

    clr(a,0);

    int x,y,i;

    FOR1(i,n) a[i][n+1]=T[i]^S[i],a[i][i]=1;

    while(scanf("%d%d",&x,&y),x||y)

    {

        a[y][x]=1;

    }

}



void Gauss()

{

    int i,j=1,k,t;

    for(i=1;i<=n;i++)

    {

        for(k=j;k<=n;k++) if(a[k][i]) break;

        if(k>n) continue;

        for(t=1;t<=n+1;t++) swap(a[k][t],a[j][t]);

        for(k=1;k<=n;k++) if(k!=j&&a[k][i])

        {

            for(t=1;t<=n+1;t++) a[k][t]^=a[j][t];

        }

        j++;

    }

    for(i=1;i<=n;i++) if(a[i][n+1])

    {

        for(k=1;k<=n;k++) if(a[i][k]) break;

        if(k>n)

        {

            puts("Oh,it's impossible~!!");

            return;

        }

    }

    PR(1<<(n-j+1));

}



int main()

{

    int num=0;

    rush()

    {

        RD(n);

        int i,j;

        FOR1(i,n) RD(S[i]);

        FOR1(i,n) RD(T[i]);

        build();

        Gauss();

    }

}

  

 

你可能感兴趣的:(poj)