HDU 3364 - Lanterns (高斯消元 + 异或方程组)
2015-02-21 21:26
369 查看
题意
有N个灯笼,m个开关。每个开关可以控制一些灯笼。现在给出灯笼的最后状态,求有几种方式可以达到。
思路
灯笼的最后状态就是开关的异或值。比如灯笼为L,开关为K。
L1=L1∗K1xorL1∗K2xorL1∗K3...xorL1∗Km
这样就是一条方程组,以此类推。
那么我们就可以根据题目列出m条方程,然后消元一下,得到自由变量的数目。
因为自由变量,也就是自由的开关数。对于每个开关,不管开或者关都行。所以答案就是1<<num
代码
#include <stack> #include <cstdio> #include <list> #include <cassert> #include <set> #include <iostream> #include <string> #include <vector> #include <queue> #include <functional> #include <cstring> #include <algorithm> #include <cctype> #include <string> #include <map> #include <cmath> using namespace std; #define LL long long #define ULL unsigned long long #define SZ(x) (int)x.size() #define Lowbit(x) ((x) & (-x)) #define MP(a, b) make_pair(a, b) #define MS(arr, num) memset(arr, num, sizeof(arr)) #define PB push_back #define X first #define Y second #define ROP freopen("input.txt", "r", stdin); #define MID(a, b) (a + ((b - a) >> 1)) #define LC rt << 1, l, mid #define RC rt << 1|1, mid + 1, r #define LRT rt << 1 #define RRT rt << 1|1 const double PI = acos(-1.0); const int INF = 0x3f3f3f3f; const double eps = 1e-8; const int MAXN = 50 + 10; const int MOD = 1e9 + 7; const int dir[][2] = { {-1, 0}, {0, -1}, { 1, 0 }, { 0, 1 } }; int cases = 0; typedef pair<int, int> pii; int A[MAXN][MAXN], M[MAXN][MAXN], n, m; LL Gauss() { //row是第几个灯, col是对应的开关. M[row][col] = 1, 说明row这个灯被col这个开关控制 int row = 0, col = 0, i, j; for (; col < m; col++) //row, col为正在检查的行列 { for (i = row; i < n; i++) //如果当前这个变量存在,跳出循环 if (M[i][col]) break; if (i == n) continue; //如果变量为0,继续下一个 if (i != row) //如果这个方程不在上一个有序的行下一行,交换这两行 for (j = col; j <= m; j++) swap(M[i][j], M[row][j]); for (i = row+1; i < n; i++) //对之后的方程消元 if (M[i][col]) //如果之后的一条方程里有这个变量,两条方程异或 for (j = col; j <= m; j++) M[i][j] ^= M[row][j]; row++; } for (i = row; i < n; i++) if (M[i][m]) return 0; //如果出现矛盾方程,即|0 0 0 0|1|出现,返回0 return 1ll << (m-row); //不然就返回2^自由变量.因为每个自由变量都可以有两种选择 } int main() { //ROP; int T; scanf("%d", &T); while (T--) { MS(A, 0); printf("Case %d:\n", ++cases); scanf("%d%d", &n, &m); for (int i = 0; i < m; i++) { int k; scanf("%d", &k); for (int j = 0; j < k; j++) { int tmp; scanf("%d", &tmp); A[tmp-1][i] = 1; //从0开始(我想到了小说 } } int q; scanf("%d", &q); while (q--) { memcpy(M, A, sizeof A); for (int i = 0; i < n; i++) scanf("%d", &M[i][m]); printf("%I64d\n", Gauss()); } } return 0; }
相关文章推荐
- 3364 Lanterns (异或方程组高斯消元)
- 3364 Lanterns (异或方程组高斯消元)
- HDU 3364 Lanterns 高斯消元(水 异或方程
- 高斯消元HDU-3364 Lanterns
- hdu 3364 Lanterns(高斯消元模板题+亦或方程)
- 【HDU 5833】Zhu and 772002(异或方程组高斯消元)
- HDU 3364 Lanterns(高斯消元入门题目——开关问题)
- HDU-#3364 Lanterns(高斯消元)
- HDU 5833 Zhu and 772002(异或方程组高斯消元)
- HDU 3364 Lanterns(高斯消元)
- hdu 3364 Lanterns (高斯消元)
- hdu 3364 Lanterns 高斯消元,模板题
- [hdu 5833 Zhu and 772002] 高斯消元求异或方程组
- hdu 3364 Lanterns(数学:高斯消元)
- hdu 3364 Lanterns 高斯消元,模板题
- Zhu and 772002 HDU - 5833 (高斯消元求异或方程组解的个数)
- 【HDU 5833】【异或方程组高斯消元】Zhu and 772002
- hdu 3364(异或方程的高斯消元)
- 【HDU3364】Lanterns-高斯消元求异或方程组的解数
- HDU 3364 Lanterns (高斯消元解开关问题)