POJ2947Widget Factory(高斯消元解同模方程)

http://poj.org/problem?id=2947

题目大意:有n 种装饰物,m 个已知条件,每个已知条件的描述如下:
p start end
a1,a2......ap (1<=ai<=n)
第一行表示从星期start 到星期end 一共生产了p 件装饰物(工作的天数为end-start+1+7*x,
加7*x 是因为它可能生产很多周),第二行表示这p 件装饰物的种类(可能出现相同的种类,
即ai=aj)。规定每件装饰物至少生产3 天,最多生产9 天。问每种装饰物需要生产的天数。
如果没有解,则输出“Inconsistent data.”,如果有多解,则输出“Multiple solutions.”,如果
只有唯一解,则输出每种装饰物需要生产的天数。

解题思路:高斯消元。设每种装饰物需要生产的天数为xi(1<=i<=n)。每一个条件就相当于
给定了一个方程式,假设生产1 类装饰物a1 件、2 类装饰物a2 件、i 类装饰物ai 件所花费
的天数为b,则可以列出下列方程:
a1*x1+a2*x2+...an*xn = b (mod 7)
这样一共可以列出m 个方程式,然后使用高斯消元来解此方程组即可。

  1 #include <map>
  2 #include <set>
  3 #include <stack>
  4 #include <queue>
  5 #include <cmath>
  6 #include <ctime>
  7 #include <vector>
  8 #include <cstdio>
  9 #include <cctype>
 10 #include <cstring>
 11 #include <cstdlib>
 12 #include <iostream>
 13 //#include <algorithm>
 14 using namespace std;
 15 #define INF 0x3f3f3f3f
 16 #define inf ((LL)1<<40)
 17 #define lson k<<1, L, mid
 18 #define rson k<<1|1, mid+1, R
 19 #define mem0(a) memset(a,0,sizeof(a))
 20 #define mem1(a) memset(a,-1,sizeof(a))
 21 #define mem(a, b) memset(a, b, sizeof(a))
 22 #define FOPENIN(IN) freopen(IN, "r", stdin)
 23 #define FOPENOUT(OUT) freopen(OUT, "w", stdout)
 24 template<class T> T ABS ( T a) { return a >= 0 ? a : -a;   }
 25 template<class T> T CMP_MIN ( T a, T b ) { return a < b;   }
 26 template<class T> T CMP_MAX ( T a, T b ) { return a > b;   }
 27 template<class T> T MAX ( T a, T b ) { return a > b ? a : b; }
 28 template<class T> T MIN ( T a, T b ) { return a < b ? a : b; }
 29 template<class T> T GCD ( T a, T b ) { return b ? GCD ( b, a % b ) : a; }
 30 template<class T> T LCM ( T a, T b ) { return a / GCD ( a, b ) * b;     }
 31 template<class T> void SWAP( T& a, T& b ) { T t = a; a = b;  b = t;     }
 32
 33 typedef __int64 LL;
 34 //typedef long long LL;
 35 const int MAXN = 310;
 36 const int MAXM = 110000;
 37 const double eps = 1e-14;
 38 const double PI = 4.0 * atan(1.0);
 39
 40 char str[7][10] = {"MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"};
 41
 42 int findNum(char *s)
 43 {
 44     for(int i = 0; i < 7; i ++ )
 45     {
 46         if(strcmp(str[i], s) == 0) return i;
 47     }
 48     return 0;
 49 }
 50 int n, m, k, cnt[MAXN];
 51 int var, equ, a[MAXN][MAXN], ans[MAXN];
 52
 53 void init()
 54 {
 55     int x;
 56     char st[10], ed[10];
 57     mem0(a);
 58     var = n;
 59     equ = m;
 60     for(int i = 0; i < m; i ++ )
 61     {
 62         mem0(cnt);
 63         scanf("%d %s %s", &k, st, ed);
 64         for(int j = 0; j < k; j ++ )
 65         {
 66             scanf("%d", &x);
 67             cnt[x-1] ++;
 68         }
 69         a[i][var] = findNum(ed) - findNum(st) + 1;
 70         for(int j = 0; j < var; j ++ )
 71             a[i][j] = cnt[j] % 7;
 72     }
 73 }
 74
 75 void exgcd(int a, int b, int& x, int& y)
 76 {
 77     if(!b) { x = 1; y = 0; }
 78     else { exgcd(b, a % b, y, x); y -= x*(a/b); }
 79 }
 80
 81 int gauss()
 82 {
 83     int x, y;
 84     int k, col = 0;
 85     for(k = 0; k < equ && col < var; k ++, col ++)
 86     {
 87         int Max = 0, row = -1;
 88         for(int r = k ; r < equ; r ++)
 89         {
 90             if( Max < ABS(a[r][col]) )
 91                 Max = ABS( a[r][col] ), row = r;
 92         }
 93         if(row == -1)
 94         {
 95             k--;
 96             continue;
 97         }
 98         for(int c = col; c <= var; c ++)
 99             SWAP(a[k][c], a[row][c]);
100         for(int r = k + 1; r < equ; r ++)
101         {
102             if(a[r][col])
103             {
104                 int lcm = LCM(ABS(a[k][col]), ABS(a[r][col]));
105                 int ta = lcm / a[r][col];
106                 int tb = lcm / a[k][col];
107                 if(a[r][col] * a[k][col] < 0) tb = -tb;
108                 for(int c = col; c <= var; c ++ )
109                 {
110                     a[r][c] = a[r][c] * ta - a[k][c] * tb;
111                     a[r][c] = (a[r][c] % 7 + 7) % 7;
112                 }
113             }
114         }
115     }
116     for(int r = k; r < equ; r ++)
117     {
118         if(a[r][var]) return -1;
119     }
120     if(k < var) return 1;
121     for(int r = var - 1; r >= 0; r --)
122     {
123         int tmp = a[r][var];
124         for(int c = var - 1; c > r; c -- )
125         {
126             tmp -= ans[c] * a[r][c] % 7;
127         }
128         tmp = (tmp % 7 + 7) % 7;
129         exgcd(a[r][r], 7, x, y);
130         ans[r] = (tmp * x % 7 + 7) % 7;
131         if(ans[r] < 3) ans[r] += 7;
132     }
133     return 0;
134 }
135
136 int main()
137 {
138     //FOPENIN("in.txt");
139     while(~scanf("%d %d", &n, &m) && (n || m))
140     {
141         init();
142         int free_num = gauss();
143         if(free_num == -1)
144         {
145             printf("Inconsistent data.\n");
146         }
147         else if(free_num == 1)
148         {
149             printf("Multiple solutions.\n");
150         }
151         else
152         {
153             for(int i = 0; i < var; i ++ )
154             {
155                 printf("%d%c", ans[i], i == var-1 ? ‘\n‘ : ‘ ‘);
156             }
157         }
158     }
159     return 0;
160 }

POJ2947Widget Factory(高斯消元解同模方程)

时间: 2024-12-23 22:02:16

POJ2947Widget Factory(高斯消元解同模方程)的相关文章

Poj 2947 widget factory (高斯消元解同模方程)

题目连接: http://poj.org/problem?id=2947 题目大意: 有n种类型的零件,m个工人,每个零件的加工时间是[3,9],每个工人在一个特定的时间段内可以生产k个零件(可以相同种类,也可以不同种类),问每种零件生产一个出来需要的时间? 解题思路: 给出的时间段是从周几到周几,并没有给出具体的时间段,因此在计算过程中要进行取模,还有就是对每个零件要在题目要求的范围内进行枚举. ps:如果求出来的增广矩阵是n*n的,但是某个零件在[3,9]之间没有合理的解,也是无解的. 1

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

题目地址:id=2947">POJ 2947 题意:N种物品.M条记录,接写来M行,每行有K.Start,End,表述从星期Start到星期End,做了K件物品.接下来的K个数为物品的编号. 此题注意最后结果要调整到3-9之间. 思路: 非常easy想到高斯消元. 可是是带同余方程式的高斯消元,開始建立关系的时候就要MOD 7 解此类方程式时最后求解的过程要用到扩展gcd的思想,举个样例,假设最后得到的矩阵为: 1  1   4 0  6   4 则6 * X2 % 7= 4 % 7  则

[ACM] POJ 2947 Widget Factory (高斯消元)

Widget Factory Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 4436   Accepted: 1502 Description The widget factory produces several different kinds of widgets. Each widget is carefully built by a skilled widgeteer. The time required to

uva 1564 - Widget Factory(高斯消元+逆元)

题目链接:uva 1564 - Widget Factory 题目大意:n种零件,m次工作日程,零件序号从1到n,给出m次工作日程的信息,x,s,e,表示生产了x个零件,从星期s开始到星期e(有可能是多个星期),然后给出生产的x个零件的序号.求每个零件被生产需要多少天(保证在3到10天) 解题思路:因为不能确定每个工作日程具体生产了几天,所以对应列出的方程均为线性模方程(模7),所以在高斯消元的过程中遇到除法要转换成乘上逆元. #include <cstdio> #include <cs

【poj2947】高斯消元求解同模方程组【没有AC,存代码】

题意: p start enda1,a2......ap (1<=ai<=n)第一行表示从星期start 到星期end 一共生产了p 件装饰物(工作的天数为end-start+1+7*x,加7*x 是因为它可能生产很多周),第二行表示这p 件装饰物的种类(可能出现相同的种类,即ai=aj).规定每件装饰物至少生产3 天,最多生产9 天.问每种装饰物需要生产的天数.如果没有解,则输出"Inconsistent data.",如果有多解,则输出"Multiple so

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

题目链接:http://poj.org/problem?id=2947 题意:有n 种装饰物,m 个已知条件,每个已知条件的描述如下: p start enda1, a2......ap (1<= ai <= n)第一行表示从星期 start 到星期 end 一共生产了p 件装饰物 (工作的天数为end - start + 1 + 7*x, 加 7*x 是因为它可能生产很多周),第二行表示这 p 件装饰物的种类(可能出现相同的种类,即 ai = aj).规定每件装饰物至少生产3 天,最多生产9

【高斯消元解XOR方程】POJ1222-EXTENDED

[题目大意] 有5*6盏灯,每次开/关一个灯,上下左右的灯状态也会反转.问怎么使状态统一? [思路] 典型高斯消元解XOR方程,注意每盏灯要么0次要么1次. 1 #include <iostream> 2 #include <stdio.h> 3 #include <algorithm> 4 #include <set> 5 using namespace std; 6 int a[40][40]; 7 void gauss() 8 { 9 int i,j,

poj1830(高斯消元解mod2方程组)

题目链接:http://poj.org/problem?id=1830 题意:中文题诶- 思路:高斯消元解 mod2 方程组 有 n 个变元,根据给出的条件列 n 个方程组,初始状态和终止状态不同的位置对应的方程右边常数项为1,状态相同的位置对于的方程组右边的常数项为0.然后用高斯消元解一下即可.若有唯一解输出1即可,要是存在 k 个变元,则答案为 1 << k, 因为每个变元都有01两种选择嘛- 代码: 1 #include <iostream> 2 #include <s

poj1753(高斯消元解mod2方程组)

题目链接:http://poj.org/problem?id=1753 题意:一个 4*4 的棋盘,初始时上面放满了黑色或白色的棋子.对 (i, j) 位置进行一次操作后 (i, j), (i + 1, j), (i - 1, j), (i, j + 1), (i, j - 1) 位置的棋子会变成原来相反的状态.问最少需要多少步可以将棋盘上的棋子全部变成白色或者黑色. 思路:分别将棋子变成黑色和白色,然后再用高斯消元解,其中步数较小者即为答案. 注意不存在唯一解时需要枚举自由变元来取得最小步数.