poj1830 開關問題

這道題也是高斯消元解異或方程組,可是書上寫的程序是有問題的。html

用這個數據能夠hack掉:ide

1spa

3code

0 0 0htm

1 1 1blog

1 2get

2 1string

2 3it

0 0io

列出矩陣:

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。

可是還有個問題:爲何不能往上回消呢?

反正記住就行了。

相關文章
相關標籤/搜索