POJ 1830 && OpenJ_Bailian 1830 开关问题 高斯消元求自由元个数

文章目录

题意

中文题.
题目链接

思路及题解

开关之间的关系非常奇怪,我们把本题的模型转化一下.
我们令 a [ i ] [ j ] a[i][j] 表示灯泡 j j 的状态是否会随着灯泡 i i 的状态改变而改变.
我们会发现,对于第 i i 个灯泡来说,都有一个方程,哪些灯泡可以通过它打开和它最后的状态.
因为每一个灯泡都是独立的,而且只有 0 , 1 0,1 两个取值,这就是一个异或方程组,我们算一下它有几个自由元,就有 2 2^{多少次方} 个解.
如果方程组没有解,显然答案也不可能.
同时因为每一位都是 0 , 1 0,1 ,可以将数组的一维压成二进制数.

#include<cstdio> //Ithea Myse Valgulious
#include<algorithm>
#include<cctype>
#include<cstring>
namespace chtholly{
typedef long long ll;
#define re0 register int
#define rec register char
#define rel register ll
#define gc getchar
#define pc putchar
#define p32 pc(' ')
#define pl puts("")
/*By Citrus*/
inline int read(){
  int x=0,f=1;char c=gc();
  for (;!isdigit(c);c=gc()) f^=c=='-';
  for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
  return f?x:-x;
  }
template <typename mitsuha>
inline bool read(mitsuha &x){
  x=0;int f=1;char c=gc();
  for (;!isdigit(c)&&~c;c=gc()) f^=c=='-';
  if (!~c) return 0;
  for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
  return x=f?x:-x,1;
  }
template <typename mitsuha>
inline int write(mitsuha x){
  if (!x) return 0&pc(48);
  if (x<0) x=-x,pc('-');
  int bit[20],i,p=0;
  for (;x;x/=10) bit[++p]=x%10;
  for (i=p;i;--i) pc(bit[i]+48);
  return 0;
  }
inline char fuhao(){
  char c=gc();
  for (;isspace(c);c=gc());
  return c;
  }
}using namespace chtholly;
using namespace std;
int a[99]; // a[]里的每一个元素代表一个异或方程,最低位表示常数项,其他位表示每一个未知数的系数.

int gauss(int n){
int i,j,k;
for (i=1;i<=n;++i){
  for (j=i+1;j<=n;++j)
    if (a[j]>a[i]) swap(a[i],a[j]);
  if (!a[i]) return n-i+1;  //  此时从i开始的每一个方程组都无限解,显然自由元有n-i+1个.
  if (a[i]==1) return -1; // 此时属于0a+0b+0c=1的情况,无解.
  for (k=n;k;--k){
    if (a[i]>>k&1){
      for (j=1;j<=n;++j) 
	    if (i^j&&(a[j]>>k&1)) 
	      a[j]^=a[i];
	  break;
	  }
    }
  }return 0;// 非常正常地消元,显然有唯一解.
}

int main(){
for (int t=read();t--;){
  int i,j,k,n=read();
  memset(a,0,sizeof a);
  for (i=1;i<=n;++i) a[i]=read();
  for (i=1;i<=n;++i) a[i]=(a[i]|(1<<i))^read();
  for (;i=read(),j=read();) a[j]|=1<<i;
  int zxy=gauss(n);
  if (~zxy) write(1<<zxy),pl;
  else puts("Oh,it's impossible~!!");
  }
}

谢谢大家.

猜你喜欢

转载自blog.csdn.net/qq_31908675/article/details/82875923