HDU 5755 高斯消元

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;
        }
    }
}



原文地址:https://www.cnblogs.com/zhangxianlong/p/10672549.html