POJ 2947 Widget Factory (高斯消元解同余方程组)

题意:N种物品,M条记录,接写来M行,每行有K,str1,str2,表示第i个记录从星期str1到星期str2,做了K件物品,接下来的K个数为物品的编号。求做每个物品所需的时间,并且最后结果在3-9之间   很容易想到高斯消元。但是是带同余方程的高斯消元,开始建立关系的时候就要MOD 7   解此类方程式时最后求解的过程要用到扩展gcd的思想,举个例子,如果最后得到的矩阵为: 1  1   4 0  6   4 则6 * X2 % 7= 4 % 7  则相当于6 * X2 + 7 * Y = 4,利用扩展gcd则可求出X2为3,则第一个方程为 X1 * 1 % 7 + 1*3 % 7 = 4 % 7 则相当于 X1 + 7 * Y = 1  得到X1=1; 但其实这道题用扩展gcd真的大材小用了,因为模数是固定的而且很小就是7,所以直接枚举试就可以了~~  
#include 
 
   
    
  
#include 
  
    
      #include 
     
       #include 
      
        #include 
       
         #include 
        
          #include 
         
           #include 
          
            #include 
            #include 
            
              #include 
             
               #include 
              
                #define MID(x,y) ((x+y)>>1) using namespace std; typedef long long LL; 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; } const int MAX_EQU = 310; typedef struct equation_set{ int equ, var; //方程个数、变元个数,则增广矩阵有equ行、var+1列. int mat[MAX_EQU][MAX_EQU+1]; //增广矩阵 int x[MAX_EQU]; //方程解向量 bool free_x[MAX_EQU]; //判断是否是不确定变元 void init(int in_equ, int in_var); void debug(); int gauss(); }EQU; void equation_set::init(int in_equ, int in_var){ equ = in_equ; var = in_var; memset(mat, 0, sizeof(mat)); memset(x, 0, sizeof(x)); memset(free_x, 1, sizeof(free_x)); } void equation_set::debug(){ for (int i = 0; i < equ; i ++){ for (int j = 0; j < var; j ++) cout << mat[i][j] << " "; cout << mat[i][var] << endl; } } int equation_set::gauss(){ int row = 0, col = 0; int max_row; while (row < equ && col < var){ max_row = row; for (int i = row + 1; i < equ; i ++) if (abs(mat[i][col]) > abs(mat[max_row][col])) max_row = i; if (max_row != row){ for (int j = 0; j <= var; j ++){ int tmp = mat[row][j]; mat[row][j] = mat[max_row][j]; mat[max_row][j] = tmp; } } if (mat[row][col] == 0){ col ++; continue; } //普通方程组行阶梯化: for (int i = row + 1; i < equ; i ++){ if (mat[i][col] != 0){ int LCM = lcm(abs(mat[i][col]), abs(mat[row][col])); int ta = LCM / abs(mat[i][col]), tb = LCM / abs(mat[row][col]); if (mat[i][col] * mat[row][col] < 0) tb = -tb; for (int j = 0; j <= var; j ++) mat[i][j] = ((mat[i][j] * ta - mat[row][j] * tb) % 7 + 7) % 7; } } row++, col++; } //debug(); //1. 无解 for (int i = row; i < equ; i++){ if (mat[i][col] != 0) return -1; } //2.无穷解(这里只是计算出了确定变元,对于多解的计算,需要枚举自由变元的状态或者其他方法求解.) if (row < var){ return 1; } //3.唯一解 for (int i = row - 1; i >= 0; i --){ int tmp = (mat[i][var] % 7 + 7) % 7; for (int j = var - 1; j > i; j --) tmp = ((tmp - x[j] * mat[i][j]) % 7 + 7) % 7; while(tmp % mat[i][i] != 0) tmp += 7; x[i] = (tmp / mat[i][i] % 7 + 7) % 7; } return 0; } int week(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 if (strcmp(s, "SUN") == 0) return 7; } int main(){ int n,m; while(scanf("%d%d", &n, &m) == 2){ if (n + m == 0) break; EQU E; E.init(m, n); for (int i = 0; i < m; i ++){ int k; char s1[10], s2[10]; scanf("%d", &k); scanf("%s%s", s1, s2); E.mat[i][n] = (week(s2) - week(s1) + 1) % 7; for (int j = 0; j < k; j ++){ int tmp; scanf("%d", &tmp); E.mat[i][tmp-1] ++; } for (int j = 0; j < n; j ++) E.mat[i][j] %= 7; } //E.debug(); int p = E.gauss(); if (p == -1){ printf("Inconsistent data.\n"); } else if (p == 1){ printf("Multiple solutions.\n"); } else{ for (int i = 0; i < n; i ++) if(E.x[i] < 3) E.x[i] += 7; for (int i = 0; i < n - 1; i ++) printf("%d ", E.x[i]); printf("%d\n", E.x[n-1]); } } return 0; } 
               
              
             
           
          
         
        
       
      
    
 
   
 

你可能感兴趣的:(factory)