开关问题
Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 9883 | Accepted: 3971 |
Description
有N个相同的开关,每个开关都与某些开关有着联系,每当你打开或者关闭某个开关的时候,其他的与此开关相关联的开关也会相应地发生变化,即这些相联系的开关的状态如果原来为开就变为关,如果为关就变为开。你的目标是经过若干次开关操作后使得最后N个开关达到一个特定的状态。对于任意一个开关,最多只能进行一次开关操作。你的任务是,计算有多少种可以达到指定状态的方法。(不计开关操作的顺序)
Input
输入第一行有一个数K,表示以下有K组测试数据。
每组测试数据的格式如下:
第一行 一个数N(0 < N < 29)
第二行 N个0或者1的数,表示开始时N个开关状态。
第三行 N个0或者1的数,表示操作结束后N个开关的状态。
接下来 每行两个数I J,表示如果操作第 I 个开关,第J个开关的状态也会变化。每组数据以 0 0 结束。
每组测试数据的格式如下:
第一行 一个数N(0 < N < 29)
第二行 N个0或者1的数,表示开始时N个开关状态。
第三行 N个0或者1的数,表示操作结束后N个开关的状态。
接下来 每行两个数I J,表示如果操作第 I 个开关,第J个开关的状态也会变化。每组数据以 0 0 结束。
Output
如果有可行方法,输出总数,否则输出“Oh,it's impossible~!!” 不包括引号
Sample Input
2 3 0 0 0 1 1 1 1 2 1 3 2 1 2 3 3 1 3 2 0 0 3 0 0 0 1 0 1 1 2 2 1 0 0
Sample Output
4 Oh,it's impossible~!!
思路:
高斯消元:a*X=b
若第x个开关跟第y个相连,则系数矩阵中a[y][x]=1,初始化中a[i][i]=1,初始情况和最后情况亦或一下就是我们的b矩阵。
代码:
1 //#include"bits/stdc++.h" 2 #include<sstream> 3 #include<iomanip> 4 #include"cstdio" 5 #include"map" 6 #include"set" 7 #include"cmath" 8 #include"queue" 9 #include"vector" 10 #include"string" 11 #include"cstring" 12 #include"time.h" 13 #include"iostream" 14 #include"stdlib.h" 15 #include"algorithm" 16 #define db double 17 #define ll long long 18 #define vec vector<ll> 19 #define mt vector<vec> 20 #define ci(x) scanf("%d",&x) 21 #define cd(x) scanf("%lf",&x) 22 #define cl(x) scanf("%lld",&x) 23 #define pi(x) printf("%d ",x) 24 #define pd(x) printf("%f ",x) 25 #define pl(x) printf("%lld ",x) 26 //#define rep(i, x, y) for(int i=x;i<=y;i++) 27 #define rep(i, n) for(int i=0;i<n;i++) 28 const int N = 1e2+ 5; 29 //const int mod = 1e9 + 7; 30 //const int MOD = mod - 1; 31 const int inf = 0x3f3f3f3f; 32 const db PI = acos(-1.0); 33 const db eps = 1e-10; 34 using namespace std; 35 int equ,var;//equ个方程,var个变量,增广矩阵行数为equ,列数为var+1,分别为0到var 36 int a[N][N];//增广矩阵 37 int x[N];//存储自由变元 38 int f_x[N]; 39 int free_x;//自由变元个数 40 void swap(int &x,int &y){ 41 int t; 42 t=x,x=y,y=t; 43 } 44 int Gauss() 45 { 46 int ma_r,col,k; 47 free_x=0; 48 for(k=0,col=0;k<equ&&col<var;k++,col++){ 49 ma_r = k; 50 for (int i = k + 1; i < equ; i++) if (abs(a[i][col] > abs(a[ma_r][col]))) ma_r = i;//取系数最大的一行 51 if (!a[ma_r][col]) { 52 k--; 53 f_x[free_x++] = col; 54 continue; 55 } 56 if (ma_r != k) 57 for (int j = col; j < var + 1; j++) swap(a[k][j], a[ma_r][j]);//与当前行交换 58 59 for (int i = k + 1; i < equ; i++) 60 if (a[i][col] != 0) 61 for (int j = col; j < var + 1; j++) a[i][j] ^= a[k][j];//消除其他行第col列的变量 62 } 63 for(int i=k;i<equ;i++) if(a[i][col]!=0) return -1;//没被消除则无解 64 65 if(k<var) return var-k;//自由变元个数 66 //唯一解,回代 67 for(int i=var-1;i>=0;i--){ 68 x[i]=a[i][var]; 69 for(int j=i+1;j<var;j++) x[i]^=(a[i][j]&&x[j]);//自下而上 70 } 71 return 0; 72 } 73 int n; 74 int main() 75 { 76 int t; 77 ci(t); 78 for(int I=1;I<=t;I++){ 79 memset(a,0,sizeof(a)); 80 ci(n); 81 int x, y; 82 for (int i = 0; i < n; i++) ci(a[i][n]); 83 for (int i = 0; i < n; i++) ci(x), a[i][n] ^= x; 84 for (int i = 0; i < n; i++) a[i][i] = 1; 85 while (scanf("%d%d", &x, &y), x + y) a[y-1][x-1] = 1; 86 equ = n, var = n; 87 int ans = Gauss(); 88 if(ans == -1) puts("Oh,it's impossible~!!"); 89 else 90 pl(1ll << ans); 91 } 92 return 0; 93 }