高斯消元2:开关问题
作者:
总打瞌睡的天天啊
,
2024-08-07 22:26:43
,
所有人可见
,
阅读 3
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 35;
int n;
int a[N][N];
int gauss()
{
int r,c;
for(r=1,c=1;c<=n;c++)
{
// 找主元
int t = r;
for(int i=r+1;i<=n;i++)
if(a[i][c])
t=i;
if(!a[t][c])continue;//不保证唯一解--不一定有主元
// 交换主元行至r行
for(int i=c;i<=n+1;i++)swap(a[t][i],a[r][i]);
// 用第r行的a[r][j]消第i行的a[i][j] 前提是第i行的最左边是1(有主元)
for(int i=r+1;i<=n;i++)
for(int j=n+1;j>=c;j--)
//等价于if(a[i][c]) a[i][j]^=a[r][j]
a[i][j] ^= a[i][c] & a[r][j];
//不能写a[i][j] ^= a[i][r] & a[r][j];
//是因为可能存在中间无主元的情况 此时r不++了 c还在循环中++ 导致r!=c
r++;
}
int res = 1;
//此时已经到了全零行
if (r < n + 1)
{
for (int i = r; i <= n; i ++ )
{
// 全零行的右边出现非零 无解
if (a[i][n + 1]) return -1; // 出现了 0 == !0,无解
res *= 2;
}
}
return res;
}
int main()
{
int T;
cin >> T;
while(T--)
{
memset(a,0,sizeof a);
cin >> n;
for(int i=1;i<=n;i++) cin >> a[i][n+1];//初始状态
for(int i=1;i<=n;i++)
{
int t;
cin >> t;
a[i][n+1]^=t;//关心a[i][n+1](初始状态)和t(新状态)有没有发生变化
a[i][i]=1;//第i个开关一定会改变第i个灯
}
int x,y;
while(scanf("%d%d",&x,&y),x||y)
a[y][x]=1;
//第y个等式(行)的右边(开关y状态) 左边(操作开关x)(第x列)的系数=1
int t = gauss();
if (t == -1) puts("Oh,it's impossible~!!");
else printf("%d\n", t);
}
return 0;
}