题意:有n堆石子,每个人只能从某一堆至少拿走一个,不能拿者败。问事先拿走某些堆的石子,使得先手必败。

由结论可知,石子数异或等于0时,先手必败。

将石子拆成二进制,未知数为1表示保留该堆石子,为0表示事先拿走该堆石子。最后2^(自由元的个数)%MOD就是答案。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define MAXN 110
 4 #define MOD 1000007
 5 using namespace std;
 6 int a[MAXN], g[MAXN][MAXN];
 7 int Gauss(int n) {
 8     int i, j, r, c, cnt;
 9     for (c = cnt = 0; c < n; c++) {
10         for (r = cnt; r < 31; r++) {
11             if (g[r][c])
12                 break;
13         }
14         if (r < 31) {
15             if (r != cnt) {
16                 for (i = 0; i < n; i++)
17                     swap(g[r][i], g[cnt][i]);
18             }
19             for (i = cnt + 1; i < 31; i++) {
20                 if (g[i][c]) {
21                     for (j = 0; j < n; j++)
22                         g[i][j] ^= g[cnt][j];
23                 }
24             }
25             cnt++;
26         }
27     }
28     return n - cnt;
29 }
30 int main() {
31     int c;
32     int n, i, j;
33     int ans, vary;
34     scanf("%d", &c);
35     while (c--) {
36         scanf("%d", &n);
37         for (i = 0; i < n; i++)
38             scanf("%d", &a[i]);
39         for (i = 0; i < 31; i++) {
40             for (j = 0; j < n; j++)
41                 g[i][j] = (a[j] >> i) & 1;
42         }
43         vary = Gauss(n);
44         for (ans = 1; vary--;) {
45             ans <<= 1;
46             ans %= MOD;
47         }
48         printf("%d\n", ans);
49     }
50     return 0;
51 }
posted on 2012-09-02 21:16  DrunBee  阅读(642)  评论(0编辑  收藏  举报