思路:
n*m个数变化,设置n*m个变量,每个位置对应5个变量发生改变,连立n*m个方程,高斯消元求解,注意取模。
// hdu 5755
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int a[950][950];
int x[950];
int gcd(int a, int b)
{
int t;
while(b)
{
int t = b;
b = a%b;
a = t;
}
return a;
}
int lcm(int a, int b)
{
int g = gcd(a, b);
return a / g * b;
}
int guass(int n)
{
int row, col;
for(row = 0, col = 0; row < n && col < n; row++, col++)
{
int maxr = row;
for(int i = row+1; i < n; i++)
if(abs(a[i][col]) > abs(a[maxr][col]))
maxr = i;
if(a[maxr][col] == 0)
{
row--;
continue;
}
if(maxr != row)
for(int j = col; j <= n; j++)
swap(a[maxr][j], a[row][j]);
for(int i = row+1; i < n; i++)
if(a[i][col])
{
int lc = lcm(abs(a[row][col]), abs(a[i][col]));
int la = lc / abs(a[row][col]);
int lb = lc / abs(a[i][col]);
if(a[i][col] * a[row][col] < 0)
la = -la;
for(int j = col; j <= n; j++)
a[i][j] = ((a[i][j] * lb - a[row][j] * la) % 3 + 3) % 3;
}
}
int ans = 0;
memset(x, 0, sizeof(x));
for(int i = row - 1; i >= 0; i--)
{
int tmp = a[i][n];
for(int j = i+1; j < n; j++)
if(a[i][j])
tmp = ((tmp - a[i][j] * x[j]) % 3 + 3 ) % 3;
x[i] = tmp * a[i][i] % 3;
if(x[i])
ans += x[i];
}
return ans;
}
int main(int argc, char const *argv[])
{
int t;
scanf("%d", &t);
while(t--)
{
int n, m;
memset(a, 0, sizeof(a));
scanf("%d%d", &n, &m);
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
{
int tmp;
scanf("%d", &tmp);
int k = i * m + j;
a[k][n*m] = (3 - tmp) % 3;
a[k][k] = 2;
if(i >= 1) a[k][k-m] = 1;
if(j >= 1) a[k][k-1] = 1;
if(i < n-1) a[k][k+m] = 1;
if(j < m-1) a[k][k+1] = 1;
}
n *= m;
printf("%d\n", guass(n));
for(int i = 0; i < n; i++)
while(x[i]--)
printf("%d %d\n", i/m+1, i%m+1);
}
return 0;
}