POJ2947 高斯消元 xingxing在努力

    这道题可以抽象成k1*x1+k2*x2+k3*x3+...+kn*xn = y (mod 7), 列很多这样的方程, 使用高斯消元法解就行。注意高斯消元一般和同余方程联系在一起, 所以在构造增广矩阵的时候应该给所有元素(a%mod+mod)%mod, 在高斯消元的过程中也不应该落下,代码如下:

 

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;
const int maxn = 300 + 10;
int a[maxn][maxn];
int n, m;         //m个方程 n个变量

void debug()
{
    printf("debug-------------\n");
    for(int i=0; i<m; i++)
    {
        for(int j=0; j<=n; j++)
            printf("%d ", a[i][j]);
        printf("\n");
    }
}
int getnum(char s[])
{
    if(s[2]=='N' && s[0]=='M') return 0;
    else if(s[2]=='E') return 1;
    else if(s[2]=='D') return 2;
    else if(s[2]=='U') return 3;
    else if(s[2]=='I') return 4;
    else if(s[2]=='T') return 5;
    else if(s[2]=='N'&&s[0]=='S') return 6;
    return -1;
}

int gcd(int n, int m)
{
    return m==0? n:gcd(m, n%m);
}

int lcm(int n, int m)
{
    return n/gcd(n, m)*m;
}

int equ, var;   //equ个方程 var个变量
int ans[maxn];    //解空间
int free_x[maxn], free_num;

int gauss()
{
    free_num = 0;
    int k, col;
    for(k=0,col=0; k<equ&&col<var; k++,col++)
    {   //处理第k个方程第col个变量
        int 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(max_r != k)   //交换第k行和第max_r行
            for(int j=k; j<=var; j++)
                swap(a[k][j], a[max_r][j]);
        if(a[k][col] == 0)
        {
            k--;
            free_x[free_num++] = col;
            continue;
        }
        for(int i=k+1; i<equ; i++)    //用第k个方程消第i个方程
        {
            if(a[i][col] == 0) continue;
            int LCM = lcm(a[k][col], a[i][col]);
            int ta = LCM/a[k][col];
            int tb = LCM/a[i][col];
            for(int j=col; j<=var; j++)
            {
                a[i][j] = a[i][j]*tb - a[k][j]*ta;
                a[i][j] = (a[i][j]%7+7)%7;       //////////////   这个一定要加
            }
        }
    }
    //debug();
    for(int i=k; i<equ; i++)
        if(a[i][col] != 0) return -1;
    if(k < n) return -2;
    for(int i=k-1; i>=0; i--)   //逐个处理方程
    {
        int tmp = a[i][var];
        for(int j=i+1; j<var; j++)
            tmp = (tmp-ans[j]*a[i][j])%7;                        //这里也要处理

        while(tmp%a[i][i] != 0)                                  //偷懒了
            tmp += 7;
        ans[i] = tmp/a[i][i];
        while(ans[i] < 3) ans[i]+=7;
        while(ans[i]>9) ans[i]-=7;
    }
    return 1;
}


int main()
{
    //freopen("in.txt", "r", stdin);
    while(scanf("%d%d", &n, &m)==2)
    {
        if(n==0&&m==0) break;
        memset(a, 0, sizeof(a));  //开始构造增广矩阵
        for(int i=0; i<m; i++)
        {
            int t;
            char s1[10], s2[10];
            scanf("%d%s%s", &t, s1, s2);
            a[i][n] = getnum(s2)-getnum(s1)+1;
            a[i][n] = (a[i][n]%7 + 7)%7;                               //这个也不能落下
            if(a[i][n]==0) a[i][n] = 7;
            for(int j=0; j<t; j++)
            {
                int tp;
                scanf("%d", &tp);
                a[i][tp-1]++;
                a[i][tp-1] = (a[i][tp-1]%7 + 7)%7;                    //同样这里要处理
            }
        }
        //debug();
        equ = m; var = n;
        int flog = gauss();
        if(flog == -1)
            printf("Inconsistent data.\n");
        else if(flog == -2)
            printf("Multiple solutions.\n");
        else
        {
            for(int i=0; i<n; i++)
                printf("%d%c", ans[i], i==n-1?'\n':' ');
        }
    }
    return 0;
}

 

posted @ 2015-11-24 13:12  xing-xing  阅读(114)  评论(0)    收藏  举报