您的位置:首页 > 其它

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  acm hdu 多校 高斯消元