参考:http://www.cnblogs.com/yohaha/p/5710264.html
2016 Multi-University Training Contest 3 1004 HDU 5755 Gambler Bo
高斯消元解同余方程组,我做的高斯消元的第一个题,解法完全是参考别人的,写博客就是存个板。
#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<string.h>
#include<math.h>
using namespace std;
const int MAXN=905;
int dx[] = {0,1,0,-1};
int dy[] = {1,0,-1,0};
int b[MAXN];
int a[MAXN][MAXN];//增广矩阵
int x[MAXN];//解集
bool free_x[MAXN];//标记是否是不确定的变元
int n,m;
const int mod = 3;
int gcd(int a, int b)
{
return b?gcd(b, a%b):a;
}
int lcm(int a, int b)
{
return a/gcd(a, b)*b;
}
long long inv(long long a, long long m)
{
if(a == 1)
return 1;
return inv(m%a, m)*(m-m/a)%m;
}
void gauss(int equ, int var)
{
int max_r, col, k;
for(k = 0, col = 0; k < equ && col < var; k++, col++)
{
max_r = k;
for(int i = k + 1; i < equ; i ++)
{
if(abs(a[i][col]) > abs(a[max_r][col]))
max_r = i;
}
if(a[max_r][col] == 0)
{
k--;
continue;
}
if(max_r != k)
{
for(int j = col; j < var+1; j++)
{
swap(a[k][j], a[max_r][j]);
}
}
for(int i = k + 1; i < equ; i++)
{
if(a[i][col])
{
int LCM = lcm(abs(a[i][col]), abs(a[k][col]));
int ta = LCM/abs(a[i][col]);
int tb = LCM/abs(a[k][col]);
if(a[i][col] * a[k][col] < 0)
tb = -tb;
for(int j = col; j < var+1; j++)
{
a[i][j] = ((a[i][j]*ta - a[k][j]*tb)%mod+mod)%mod;
}
}
}
for(int i = var-1; i >= 0; i--)
{
int tmp = a[i][var];
for(int j = i+1; j < var; j++)
{
if(a[i][j])
{
tmp -= a[i][j]*x[j];
tmp = (tmp%mod+mod)%mod;
}
}
x[i] = a[i][i]*tmp%mod;
}
}
}
bool ok(int x)
{
if(x >= 0 && x < m*n)
return 1;
return 0;
}
int main(void)
{
int t;
scanf("%d", &t);
while(t--)
{
memset(x,0,sizeof(x));
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
scanf("%d%d", &m, &n);
for(int i = 0; i < m * n; ++i)
scanf("%d", &b[i]);
for(int i = 0; i < m * n; ++i)
{
int r = i + 1, l = i - 1, u = i - n, d = i + n;
if(ok(r) && (i+1) % n != 0)
a[i][r] = 1;
if(ok(l) && i % n != 0)
a[i][l] = 1;
if(ok(u))
a[i][u] = 1;
if(ok(d))
a[i][d] = 1;
a[i][i] = 2;
a[i][m*n] = (3 - b[i]) % 3;
}
gauss(n*m,n*m);
int cnt = 0;
for(int i = 0; i < n*m; ++i)
cnt += x[i];
printf("%d\n", cnt);
for(int i = 0; i < n*m; ++i)
while(x[i])
{
printf("%d %d\n", i/n+1,i%n+1);
x[i]--;
}
}
return 0;
}