POJ2947 Widget Factory [高斯消元]

W i d g e t    F a c t o r y \mathcal{Widget\ \ Factory} Widget  Factory


D e s c r i p t i o n \mathcal{Description} Description

存在 N N N 种零件, 加工 i i i 零件需要 c o s t i cost_i costi 的时间, 且 c o s t i cost_i costi 未知; 现给出 M M M 条信息, 每条信息包括一个工人的 聘用时刻解雇时刻, 其加工了 K 个 零 件 K个零件 K. 时刻都以 星 期 X     ( X ∈ [ 1 , 7 ] ) 星期X\ \ \ (X∈[1,7]) X   (X[1,7]) 来表示, 无具体日期.

请求出所有 c o s t i cost_i costi .
若无解输出 Inconsistent data.
若多解输出 Multiple solutions.

K<=10000, N,M<=300


S o l u t i o n \mathcal{Solution} Solution

列出 M M M m o d   7 mod \ 7 mod 7 的同余方程 .

F o r    e x a m p l e : For \ \ example: For  example:


a 1 , 1 x 1 + a 1 , 2 x 2 + . . . + a 1 , n x n ≡ 5        ( m o d    7 ) a_{1,1}x_1+a_{1,2}x_2+...+a_{1,n}x_n \equiv 5\ \ \ \ \ \ (mod\ \ 7) a1,1x1+a1,2x2+...+a1,nxn5      (mod  7)
高斯消元后若得出 上三角矩阵, 则对最后一行进行分析 :
b b b 为常数,
a m , n x n ≡ b        ( m o d    7 )   a m , n x n + 7 y = b a_{m,n}x_n \equiv b \ \ \ \ \ \ (mod \ \ 7)\\ \ \\ a_{m,n}x_n +7y = b am,nxnb      (mod  7) am,nxn+7y=b

使用 E x _ g c d Ex\_gcd Ex_gcd 求出 x n x_n xn, 回带到前一个方程
a m − 1 , n − 1 x n − 1 + a m − 1 , n x n ≡ b 2        ( m o d    7 ) a_{m-1,n-1}x_{n-1}+a_{m-1,n}x_n \equiv b_2\ \ \ \ \ \ (mod\ \ 7) am1,n1xn1+am1,nxnb2      (mod  7)

此时将 x n x_n xn 项移动到右边, 又可以采用 E x _ g c d Ex\_gcd Ex_gcd 进行求解了.
于是不断 求解, 回带, 最后即可得出所有解.

注意高斯消元时不能产生小数, 所以要使用 L C M LCM LCM 进行消元.


C o d e \mathcal{Code} Code

Bug Code

#include<bits/stdc++.h>
#define reg register

int read(){
        char c;
        int s = 0, flag = 1;
        while((c=getchar()) && !isdigit(c))
                if(c == '-'){ c = getchar(), flag = -1; break; }
        while(isdigit(c)) s = s*10 + c-'0', c = getchar();
        return s * flag;
}

const int maxn = 305;

int FUCK;
int N;
int M;
int K;
int Ans[maxn];
int A[maxn][maxn];

std::string st;
std::string ed;

int Ex_gcd(int a, int b, int &x=FUCK, int &y=FUCK){
        if(!b){ x = 1, y = 0; return a; }
        int tmp = Ex_gcd(b, a%b, y, x);
        y -= (a/b) * x;
        return tmp;
}

int Trans(std::string s){
        if(s == "MON") return 1;
        else if(s == "TUE") return 2;
        else if(s == "WED") return 3;
        else if(s == "THU") return 4;
        else if(s == "FRI") return 5;
        else if(s == "SAT") return 6;
        return 7;
}

int Guass(){
        int t = 1;
        for(reg int i = 1; i <= N && t <= M; i ++, t ++){
                int max_id = 0;
                for(reg int j = t; j <= M; j ++)
                        if(A[j][i]){ max_id = j; break ; }
                if(!max_id){ t --; continue ; }
                if(max_id != t) std::swap(A[max_id], A[t]);
                for(reg int j = t+1; j <= M; j ++){
                        if(!A[j][i]) continue ;
                        int a = A[j][i], b = A[t][i];
                        int lcm = a/Ex_gcd(a, b) * b;
                        int tmp_1 = lcm/b, tmp_2 = lcm/a;
                       // printf("LCM: %d tmp_1: %d tmp_2: %d\n", lcm, tmp_1, tmp_2);
                        for(reg int k = i; k <= N+1; k ++){
                                int &p = A[j][k];
                                p = p*tmp_2 - A[t][k]*tmp_1;
                                p = p%7 + 7;
                                if(p >= 7) p -= 7;
                        }
                }
        }

  //              printf("======= %d ====\n", N-t+1);
        if(t <= N){
                for(reg int i = t; i <= N; i ++)
                        if(A[i][N+1]) return -1;  // No solution
                return 0;   // More than one solution
        }

        /*
        for(int i=1;i<=N;i++){

           for(int j=1;j<=N+1;j++) printf("%d ", A[i][j]);
           printf("\n");
}
printf("=============\n");
*/

        int y;
        for(reg int i = N; i >= 1; i --){ 
                int &p = A[i][N+1];
                for(reg int j = i+1; j <= N; j ++) p -= A[i][j] * Ans[j];
                p = (p%7 + 7) % 7;                
                
                int gcd = Ex_gcd(A[i][i], 7, Ans[i], y);
                Ans[i] *= p/gcd;
                Ans[i] = (Ans[i]%7 + 7) % 7;
                if(Ans[i] < 3) Ans[i] += 7;     //#
                
               /*
                for(reg int j = 3; j <= 9; j ++)
                        if(((A[i][i]*j%7)+7)%7 == A[i][N+1]){
                                Ans[i] = j;
                                break ;
                        }
                        */
        }
        return 1;
}

void Work(){ 
        memset(A, 0, sizeof A);
        for(reg int i = 1; i <= M; i ++){ 
                K = read(); 
                std::cin >> st >> ed;
                int t_1 = Trans(ed), t_2 = Trans(st);
                A[i][N+1] = ((t_1 - t_2 + 1)%7 + 7) % 7;
                while(K --){
                        A[i][A[i][0]=read()] ++;
                        if(A[i][A[i][0]] >= 7) A[i][A[i][0]] -= 7;
                }
        }

/*
        for(int i=1;i<=N;i++){

           for(int j=1;j<=N+1;j++) printf("%d ", A[i][j]);
           printf("\n");
}
printf("=============\n");
*/

        int flag = Guass();
        if(flag == -1) printf("Inconsistent data."); 
        else if(!flag) printf("Multiple solutions.");
        else for(reg int i = 1; i <= N; i ++) printf("%d ", Ans[i]);
        printf("\n");
}

int main(){
        freopen("My.in", "r", stdin);
        freopen("My.out", "w", stdout);
        while((N = read()) && (M = read())) Work();
        return 0;
}




std

#include<stdio.h>
#include<string.h>
#include<algorithm>
#define MOD 7
using namespace std;
int m,n,matrix[310][310],ans[310];
int get_id(char s[])
{
    char week[8][5]={"","MON","TUE","WED","THU","FRI","SAT","SUN"};
    int i;
    for(i=1;i<=7;i++)
        if(strcmp(s,week[i])==0)
            break;
    return i;
}
int ex_gcd(int a,int b,int &x,int &y)
{
    int t,d;
    if(b==0){
        x=1;
        y=0;
        return a;
    }
    d=ex_gcd(b,a%b,x,y);
    t=x;
    x=y;
    y=t-a/b*y;
    return d;
}
int Lcm(int a,int b)
{
    int x,y;
    return a*b/ex_gcd(a,b,x,y);
}
int guass()
{
    int i,j,row,col;
    for(row=0,col=0;row<n&&col<m;row++,col++){
        for(i=row;i<n;i++)
            if(matrix[i][col])
                break;
        if(i==n){          //col列全为0
            row--;
            continue;
        }
        if(i!=row)
            for(j=0;j<=m;j++)
                swap(matrix[row][j],matrix[i][j]);   //交换两行
        for(i=row+1;i<n;i++){          
            if(matrix[i][col]){
                int lcm=Lcm(matrix[row][col],matrix[i][col]);
                int t1=lcm/matrix[i][col],t2=lcm/matrix[row][col];
                printf("LCM: %d tmp_1: %d tmp_2: %d\n", lcm, t1, t2);
                for(j=col;j<=m;j++)
                    matrix[i][j]=((matrix[i][j]*t1-matrix[row][j]*t2)%MOD+MOD)%MOD;
            }
        }
    }
    printf("===== %d =====\n", m-row);
    for(i=row;i<n;i++)     
        if(matrix[i][m])          //无解
            return -1;
    if(row<m)                    //有无穷解
        return 0;
        for(int i=0;i<m;i++){

           for(int j=0;j<=m;j++) printf("%d ", matrix[i][j]);
           printf("\n");
}
printf("=============\n");
    memset(ans,0,sizeof(ans));  //唯一解求解过程如下
    for(i=n-1;i>=0;i--){        
        int temp=0;
        for(j=i+1;j<m;j++)
            temp=(temp+matrix[i][j]*ans[j]%MOD)%MOD;
        int b=((matrix[i][m]-temp)%MOD+MOD)%MOD;
        int x,y;
        int d=ex_gcd(matrix[i][i],MOD,x,y);  //解模线性方程
        x=x*(b/d)%MOD;
        x=(x%(MOD/d)+(MOD/d))%(MOD/d);
        ans[i]=x;
        if(ans[i]<3)
            ans[i]+=7;
    }
    return 1;
}
int main()
{
        freopen("My.in", "r", stdin);
        freopen("std.out", "w", stdout);
    int num,i,j,type;
    char start[5],end[5];
    while(scanf("%d%d",&m,&n)!=EOF){
        if(m==0&&n==0) break;
        memset(matrix,0,sizeof(matrix));
        for(i=0;i<n;i++){
            scanf("%d%s%s",&num,start,end);
            matrix[i][m]=((get_id(end)-get_id(start)+1)%MOD+MOD)%MOD; //求生产时间对7取余
            for(j=1;j<=num;j++){
                scanf("%d",&type);
                matrix[i][type-1]=(matrix[i][type-1]+1)%MOD;   //记录矩阵的值
            }
        }

        for(i=0;i<m;i++){

           for(j=0;j<=m;j++) printf("%d ", matrix[i][j]);
           printf("\n");
}
printf("=============\n");


        int flag=guass();   //高斯消元
        if(flag==-1)
            printf("Inconsistent data.\n");
        else if(flag==0)
            printf("Multiple solutions.\n");
        else{
            for(i=0;i<m-1;i++)
                printf("%d ",ans[i]);
            printf("%d\n",ans[m-1]);
        }
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值