http://acm.hdu.edu.cn/showproblem.php?pid=5755
题意:一个N*M的棋盘,每个点是0,1,2中的一个,在取模3的含义下,翻转一个这个+2,周围的4个加1.。。。
思路:感慨一下知识面太狭隘了。。学习了一下高斯消元,这个题目其实就是高斯消元的一个经典题目。。每个结点的翻转次数都是一个变量。。猛地一看时间复杂度是n^3m^3但是高斯消元里面变量前的系数如果是0就不进行迭代了。。这么一看原题列出的增广矩阵明显是一个稀疏矩阵,一行最多只有五个系数非零。。那么就非常愉快的。。差不多可以莽一下大概n^2m^2的复杂度就过去了~
代码:
#include <bits/stdc++.h>
using namespace std;
const int MOD = 3;
const int MAXN = 1000;
int a[MAXN][MAXN];//增广矩阵
int x[MAXN];//最后得到的解集
inline int gcd(int a,int b){
while(b != 0){
int t = b;
b = a%b;
a = t;
}
return a;
}
inline int lcm(int a,int b){
return a/gcd(a,b)*b;
}
void zgcd(long long a,long long b,int &d,int &x,int &y){
if(!b){d=a;x=1;y=0;}
else{zgcd(b,a%b,d,y,x);y-=x*(a/b);}
}
long long mod_r(long long b,long long p){
int x,y,d;
zgcd(b,p,d,x,y);
if(d!=1) return -1;
return (x%p+p)%p;
}
int 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] != 0){
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 = k; i < equ; i++) if(a[i][col] != 0) return -1; //无解
// if(k < var) return var-k;//多解
for(int i = var-1; i >= 0; i--){
int temp = a[i][var];
for(int j = i+1; j < var; j++){
if(a[i][j] != 0){
temp -= a[i][j]*x[j];
temp = (temp%MOD + MOD)%MOD;
}
}
x[i] = (temp*mod_r(a[i][i],3))%MOD;
}
return 0;
}
int p[MAXN][2];
int main(){
int t;
scanf("%d",&t);
while(t--){
int n,m;
scanf("%d%d",&n,&m);
memset(a,0,sizeof(a));
memset(x,0,sizeof(x));
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
int num;
scanf("%d",&num);
int idx=i*m+j;
p[idx][0]=i;
p[idx][1]=j;
a[idx][n*m]=(3-num)%3;
a[idx][idx]=2;
if(i-1>=0) a[(i-1)*m+j][idx]=1;
if(i+1<n) a[(i+1)*m+j][idx]=1;
if(j-1>=0) a[i*m+j-1][idx]=1;
if(j+1<m) a[i*m+j+1][idx]=1;
}
}
Gauss(n*m,n*m);
int cnt=0;
for(int i=0;i<n*m;i++){
cnt+=x[i];
}
cout<<cnt<<endl;
for(int i=0;i<n*m;i++){
for(int j=0;j<x[i];j++)
cout<<p[i][0]+1<<" "<<p[i][1]+1<<endl;
}
}
}