(模板)poj2947(高斯消元法解同余方程组)

题目链接:https://vjudge.net/problem/POJ-2947

题意:转换题意后就是已知m个同余方程,求n个变量。

思路:

  值得学习的是这个模板里消元用到lcm的那一块。注意题目输出的答案在[3,9]之间。

AC代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdlib>
using namespace std;

const int maxn=305;
int n,m,a[maxn][maxn],x[maxn];
char s1[10],s2[10];

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;  //先除后乘
}

// 高斯消元法解方程组(Gauss-Jordan elimination).(
//-1表示无解,0表示唯一解,大于0表示无穷解,并返回自由变元的个数)
//有equ个方程,var个变元。增广矩阵行数为equ,分别为0到equ-1,列数为var+1,分别为0到var.
int Gauss(int equ,int var){
    int k,max_r,col=0,ta,tb,LCM,temp;
    for(int i=0;i<var;++i){
        x[i]=0;
    }
    for(k=0;k<equ&&col<var;++k,++col){
        max_r=k;
        //找系数绝对值最大的那一行与第k行交换
        for(int i=k+1;i<equ;++i){
            if(abs(a[i][col])>abs(a[max_r][col]))
                max_r=i;
        }
        if(max_r!=k){
            for(int i=col;i<var+1;++i)
                swap(a[max_r][i],a[k][i]);
        }
        if(!a[k][col]){
            --k;
            continue;
        }
        for(int i=k+1;i<equ;++i){
            if(!a[i][col]) continue;
            LCM=lcm(abs(a[i][col]),abs(a[k][col]));
            ta=LCM/abs(a[i][col]);
            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)%7+7)%7;
            }
        }
    }
    //无解的情况
    for(int i=k;i<equ;++i){
        if(a[i][col]) return -1;
    }
    //无穷解的情况
    if(k<var){    
        return var-k;   //返回自由变元的个数
    }
    //唯一解的情况,增广矩阵中形成严格的上三角阵
    for(int i=var-1;i>=0;--i){
        temp=a[i][var];
        for(int j=i+1;j<var;++j){
            if(!a[i][j]) continue;
            temp-=a[i][j]*x[j];
            temp=(temp%7+7)%7;
        }
        while(temp%a[i][i]!=0) temp+=7;
        x[i]=(temp/a[i][i])%7;
    }
    return 0;
}

int tran(char *s){
    if(strcmp(s,"MON")==0) return 1;
    else if(strcmp(s,"TUE")==0) return 2;
    else if(strcmp(s,"WED")==0) return 3;
    else if(strcmp(s,"THU")==0) return 4;
    else if(strcmp(s,"FRI")==0) return 5;
    else if(strcmp(s,"SAT")==0) return 6;
    else return 7;
}

int main(){
    while(scanf("%d%d",&n,&m),n||m){
        memset(a,0,sizeof(a));
        for(int i=0;i<m;++i){
            int k;
            scanf("%d%s%s",&k,s1,s2);
            a[i][n]=((tran(s2)-tran(s1)+1)%7+7)%7;
            while(k--){
                int t;
                scanf("%d",&t);
                --t;
                ++a[i][t];
                a[i][t]%=7;
            }
        }
        int ans=Gauss(m,n);
        if(ans==0){
            for(int i=0;i<n;++i)
                if(x[i]<=2) x[i]+=7;
            for(int i=0;i<n-1;++i)
                printf("%d ",x[i]);
            printf("%d\n",x[n-1]);
        }
        else if(ans==-1){
            printf("Inconsistent data.\n");
        }
        else{
            printf("Multiple solutions.\n");
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/FrankChen831X/p/11775127.html