HDU - 5755 高斯消元解同余方程
2017-03-23 14:42
363 查看
题意:
n*m的矩阵,每个矩阵都有0,1,2三种数值,一开始每个点都有一个初始值,每次可以选择一个位置+2,然后该位置的上下左右都+1,问多少次之后可以将所有位置的数值都变成0。思路:
很典型的开关问题,没什么好说的,高斯消元,不过这题不是以前的异或方程,而是模3同余方程。代码:
#include <bits/stdc++.h> using namespace std; const int MAXN = 1111; typedef int Matrix[MAXN][MAXN]; // 高斯消元解模k同余方程 struct Gauss { int A[MAXN][MAXN]; bool fre[MAXN]; int Rank, equ, var, fnum; int indx[MAXN], x[MAXN]; void init(int m, int n) { fnum = 0; equ = m; var = n; memset(fre, 0, sizeof(fre)); memset(x, 0, sizeof(x)); for(int i = 0; i <= m; i++) for(int j = 0; j <= n; j++) A[i][j] = 0; } void get_root(int m, int n, int mod) { // rank of matrix int i = 0, j = 0, k, r, u; //i:row j:col while (i < m && j < n) { r = i; for (k = i; k < m; k++) if (A[k][j]) { r = k; break ; } if (A[r][j]) { if (r != i) for (k = 0; k <= n; k++) swap(A[r][k], A[i][k]); for (u = i + 1; u < m; u++) if (A[u][j]) { int lcm = A[u][j] / __gcd(A[u][j], A[i][j]) * A[i][j]; int t1 = lcm / A[u][j], t2 = lcm / A[i][j]; for(k = i; k <= n; k++) A[u][k] = (t1 * A[u][k] % mod - t2 * A[i][k] % mod + mod) % mod; } i++; } else { fre[j] = 1; indx[fnum++] = j; } j ++; } Rank = i; k = var - 1; for (int i = Rank - 1; i >= 0 && k >= 0; i--){ //only needs to solve 'rank' num of equation? while (k >= 0 && fre[k]) k--; if (k >= 0){ x[k] = A[i][var]; for (int j = k + 1; j < var; j++) x[k] = (x[k] - A[i][j] * x[j] % mod + mod) % mod; x[k] = x[k] * A[k][k] % mod; k --; } } } } gauss; int mp[MAXN][MAXN]; const int dx[] = {-1, 1, 0, 0}; const int dy[] = {0, 0, -1, 1}; int main() { int T, n, m; scanf("%d", &T); while(T--) { scanf("%d%d", &n, &m); gauss.init(n * m, n * m); for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { scanf("%d", &mp[i][j]); int t1 = m * i + j; gauss.A[t1][t1] = 2; gauss.A[t1][n * m] = (3 - mp[i][j]) % 3; for (int k = 0; k < 4; k++){ int cx = i + dx[k], cy = j + dy[k]; if (cx >= 0 && cx < n && cy >= 0 && cy < m){ int t2 = m * cx + cy; gauss.A[t2][t1] = 1; } } } } gauss.get_root(n * m, n * m, 3); int cnt = 0; for (int i = 0; i < n * m; i++) cnt += gauss.x[i]; printf("%d\n", cnt); for (int i = 0; i < n * m; i++){ for (int j = 0; j < gauss.x[i]; j++) printf("%d %d\n", i / m + 1, i % m + 1); } } return 0; }
相关文章推荐
- HDU 5755 Gambler Bo(高斯消元解同余方程)
- HDU 5755 Gambler Bo(高斯消元)2016 Multi-University Training Contest 3
- hdu 5755(高斯消元——模线性方程组模板)
- HDU 5755 Gambler Bo(高斯消元)
- HDU-5755-Gambler Bo-高斯消元
- HDU 5755 高斯消元
- hdu 5755 Gambler Bo 高斯消元 + 取余逆元 模3系下的开关灯问题
- hdu 5755 Gambler Bo 高斯消元 + 取余逆元
- hdu 5755 Gambler Bo 三进制高斯消元(开关问题变形)
- hdu 5755(高斯消元)
- hdu 5755 Gambler Bo 高斯消元
- HDU 5755 (高斯消元)
- HDU 5755 Gambler Bo 高斯消元解同余方程组
- hdu 5755 Gambler Bo 高斯消元
- 【HDU 5755】Gambler Bo(高斯消元)
- [HDU 5755] Gambler Bo (高斯消元)
- HDU 5755 Gambler Bo(高斯消元)
- HDU 5755 Gambler Bo(高斯消元裸题)——2016 Multi-University Training Contest 3
- 2016多校第三场 1004 HDU 5755 高斯消元
- hdu 5833 Zhu and 772002 高斯消元