【HDU】3364 Lanterns

题意:n盏灯,m个开关,每个开关控制一些灯。给出n个灯的状态,询问开关的方案数,使得达到给出的状态。

灯的状态是由控制它的所有开关的状态异或而来,所以每个开关不是0,就是1。

高斯消元后,等式左边系数全为0,等式右边系数不为0,显然无解。否则答案就是2^(自由元的个数)。

 1 #include<cstdio>

 2 #include<cstring>

 3 #include<algorithm>

 4 #define MAXN 60

 5 typedef long long LL;

 6 using namespace std;

 7 int g[MAXN][MAXN], a[MAXN][MAXN];

 8 int n, m;

 9 LL Gauss() {

10     int i, j, r, c, cnt, tmp;

11     for (c = cnt = 0; c < m; c++) {

12         for (r = cnt; r < n; r++) {

13             if (g[r][c])

14                 break;

15         }

16         if (r < n) {

17             if (r != cnt) {

18                 for (i = 0; i <= m; i++)

19                     swap(g[r][i], g[cnt][i]);

20             }

21             for (i = cnt + 1; i < n; i++) {

22                 if (g[i][c]) {

23                     for (j = 0; j <= m; j++)

24                         g[i][j] ^= g[cnt][j];

25                 }

26             }

27             cnt++;

28         }

29     }

30     for (i = 0; i < n; i++) {

31         for (j = tmp = 0; j < m; j++)

32             tmp |= g[i][j];

33         if (!tmp && g[i][j])

34             return 0;

35     }

36     return 1LL << (m - cnt);

37 }

38 int main() {

39     int c, ca = 1;

40     int k, i, x, q;

41     scanf("%d", &c);

42     while (c--) {

43         scanf("%d%d", &n, &m);

44         memset(a, 0, sizeof(a));

45         for (i = 0; i < m; i++) {

46             scanf("%d", &k);

47             while (k--) {

48                 scanf("%d", &x);

49                 a[x - 1][i] = 1;

50             }

51         }

52         scanf("%d", &q);

53         printf("Case %d:\n", ca++);

54         while (q--) {

55             memcpy(g, a, sizeof(a));

56             for (i = 0; i < n; i++)

57                 scanf("%d", &g[i][m]);

58             printf("%I64d\n", Gauss());

59         }

60     }

61     return 0;

62 }

你可能感兴趣的:(ant)