题意:给你N个开关,其中某些开关之间是相互影响的,即一个开关控制多个,那么每个开关操作与否为一个变元,有N个变元,开关之间相互影响的系数设为1,否则为0,对模2高斯消元求解自由变元个数。
#include<iostream> #include<cstring> #include<cstdio> #include<cmath> using namespace std; const int maxn=30; int n,m;//有n个方程,m个未知数 int a[maxn][maxn]; int x[maxn];//解集 bool free_x[maxn];//判断是否为自由变元 int free_num;//记录自由变元的个数 int gcd(int a,int b) { return b==0?a:gcd(b,a%b); } int lcm(int a,int b) { return a*b/gcd(a,b); } //返回-2表示有浮点数解,但无整数解;返回-1表示无解;返回fjfj0表示有唯一解;返回1表示有无穷个解 int gauss() { int i,j,k; int max_r;//当前这列绝对值最大的行 int col;//当前处理的列 int ta,tb; int LCM; int temp; int free_x_num; int free_index; col=0; for(k=0;k<n&&col<m;k++,col++) {//枚举当前处理的行 max_r=k; for(i=k+1;i<n;i++) { if(abs(a[i][col])>abs(a[max_r][col])) max_r=i; } if(max_r!=k) {//与第k行交换 for(j=k;j<m+1;j++) swap(a[k][j],a[max_r][j]); } if(a[k][col]==0) {//说明该col列第k行以下全都是0了,则处理当前行的下一列 k--; continue; } for(i=k+1;i<n;i++) {//枚举要删去的行 if(a[i][col]!=0) { LCM=lcm(abs(a[i][col]),abs(a[k][col])); ta=LCM/abs(a[i][col]),tb=LCM/abs(a[k][col]); if(a[i][col]*a[k][col]<0) ta=-tb;//异号的情况是两个数相加 for(j=col;j<m+1;j++) { a[i][j]=((a[i][j]*ta)%2-(a[k][j]*tb)%2+2)%2; } } } } for(i=k;i<n;i++) { if(a[i][col]!=0) return -1; } if(k<m) { for(i=k-1;i>=0;i--) { free_x_num=0; for(j=0;j<m;j++) { if(a[i][j]!=0&&free_x[j]) free_x_num++,free_index=j; } if(free_x_num>1) continue; temp=a[i][m]; for(j=0;j<m;j++) { if(a[i][j]!=0&&j!=free_index) temp-=a[i][j]*x[j]; } x[free_index]=temp/a[i][free_index]; free_x[free_index]=0; } return m-k;//自由变元有m-k个 } for(i=m-1;i>=0;i--) { temp=a[i][m]; for(j=i+1;j<m;j++) { if(a[i][j]!=0) temp-=a[i][j]*x[j]; } if(temp%a[i][i]!=0) return -2; x[i]=temp/a[i][i]; } return 0; } int c[maxn],t[maxn]; int main() { int k,x,y; scanf("%d",&k); while(k--) { memset(a,0,sizeof a); memset(free_x,1,sizeof free_x); scanf("%d",&m); n=m; for(int i=0;i<m;i++) a[i][i]=1; for(int i=0;i<m;i++) scanf("%d",&c[i]); for(int i=0;i<m;i++) scanf("%d",&t[i]); while(scanf("%d%d",&x,&y)) { if(x==0&&y==0) break; a[y-1][x-1]=1; } for(int i=0;i<n;i++) { a[i][m]=(t[i]-c[i]+2)%2; } free_num=gauss(); //cout<<"自由变元个数:"<<free_num<<endl; if(free_num==-1||free_num==-2) puts("Oh,it's impossible~!!"); else printf("%d\n",(1<<free_num)); } return 0; }
