poj1830 开关问题

这道题也是高斯消元解异或方程组,但是书上写的程序是有问题的。

用这个数据可以hack掉:

1

3

0 0 0

1 1 1

1 2

2 1

2 3

0 0

列出矩阵:

1 1 0 1

1 1 1 1

0 0 1 1

然后就会给出无解。实际上是有2解的。


下面来看正解:

异或方程组不能往上回消,也不能像书上那样每次把上下都消了。

直接消成上三角矩阵。

答案就是 (1 << 自由元个数)

关于无解的判定:自由元常数项和前面不统一时即无解。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 const int N = 35;
 5 
 6 int a[N], n;
 7 
 8 inline int Gauss() {
 9     int ans = 0;
10     for(int i = 1; i <= n; i++) {
11         for(int j = i; j <= n; j++) {
12             if(a[j] & (1 << i)) {
13                 std::swap(a[i], a[j]);
14                 break;
15             }
16         }
17         if(!((a[i] >> i) & 1)) {
18             if((a[i] > 1) ^ (a[i] & 1)) {
19                 return -1;
20             }
21             else {
22                 ans++;
23                 continue;
24             }
25         }
26         for(int j = i + 1; j <= n; j++) {
27             if(a[j] & (1 << i)) {
28                 a[j] ^= a[i];
29             }
30         }
31     }
32     return ans;
33 }
34 
35 inline void solve() {
36     scanf("%d", &n);
37     int c, b;
38     for(int i = 1; i <= n; i++) {
39         scanf("%d", &a[i]);
40     }
41     for(int i = 1; i <= n; i++) {
42         scanf("%d", &b);
43         a[i] ^= b;
44     }
45     while(scanf("%d%d", &c, &b)) {
46         if(!c) {
47             break;
48         }
49         a[b] |= (1 << c);
50     }
51     for(int i = 1; i <= n; i++) {
52         a[i] |= (1 << i);
53     }
54 
55     int t = Gauss();
56     if(t == -1) {
57         printf("Oh,it's impossible~!!\n");
58         return;
59     }
60     printf("%d\n", 1 << t);
61     return;
62 }
63 
64 int main() {
65     int T;
66     scanf("%d", &T);
67     while(T--) {
68         solve();
69         if(T) {
70             memset(a, 0, sizeof(a));
71         }
72     }
73     return 0;
74 }
AC代码

但是不管怎么说,有一点让我很在意:

高斯消元解异或方程组的时候,两行异或这个操作的实际意义是什么?

现在我可能有答案了。

没有意义,不要联系实际,而是当成方程的形式,在每一项后面配一个xj就行了。

然后联系这一题

本题求方案数,所以可以直接用2^ans

但是那一题求最小值,而每个主元虽说固定,但是分选/不选两种。

然后自由元的选/不选虽然不会改变主元的个数,但是能改变主元的状态。

所以需要DFS。

但是还有个问题:为什么不能往上回消呢?

反正记住就好了。

 

posted @ 2018-08-21 12:47  garage  阅读(109)  评论(0编辑  收藏  举报