poj1830 开关问题(gauss)

poj上的中文题面,大家一定要亲眼见证一下

分析:
这道题和poj1222大同小异
还是异或方程求解
唯一不同的就是,需要计算方案数
这就和那些不确定的元素有关了
每个不定元都有两种选择:开或关
所以方案数就是
2^(不定元个数)

tip

怎么确定有没有解呢

for (int i=n;i>=1;i--)
    if (a[i][n+1]!=0&&a[i][i]==0)
        return 0;

不要忘了now++

注意

题目描述中:
每行两个数I J,表示如果操作第 I 个开关,第J个开关的状态也会变化
也就是说第I决定第J个,所以a[J][I]=1
所以在列方程的时候,一定要找好对应关系
这再一次说明了那条真理

样例都是逗你玩的

//这里写代码片
#include<cstdio>
#include<iostream>
#include<cstring>

using namespace std;

int cnt,n;
int mp1[35],mp2[35];
int a[35][35];

int gauss()
{
    cnt=0;
    int now=1,to;
    for (int i=1;i<=n;i++)
    {
        for (to=now;to<=n;to++)
            if (a[to][i]) break;
        if (to>n)    //不定元 
        {
            cnt++;
            now++;
            continue;
        }
        if (to!=now)
            for (int j=1;j<=n+1;j++)
                swap(a[to][j],a[now][j]);
        for (int j=1;j<=n;j++)
            if (j!=now&&a[j][i])
                for (int k=1;k<=n+1;k++)
                    a[j][k]^=a[now][k];
        now++;
    }
    for (int i=n;i>=1;i--)
        if (a[i][n+1]!=0&&a[i][i]==0)
            return 0;
    return 1;
}

int main()
{
    int T;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d",&n);
        memset(a,0,sizeof(a));
        for (int i=1;i<=n;i++) scanf("%d",&mp1[i]);
        for (int i=1;i<=n;i++) scanf("%d",&mp2[i]);
        int x,y;
        scanf("%d%d",&x,&y);
        while (x&&y)
        {
            a[y][x]=1;
            scanf("%d%d",&x,&y);
        }
        for (int i=1;i<=n;i++)
        {
            a[i][i]=1;
            a[i][n+1]=mp1[i]^mp2[i];
        }
        if (gauss())
        {
            printf("%d
",(1<<cnt));
        }
        else printf("Oh,it's impossible~!!
");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/wutongtong3117/p/7673078.html