[Gauss]POJ2947 Widget Factory

题意: 有n种小工具要加工,每种工具的加工时间为3到9天,给了m条加工记录。

    每条记录 X s1 s2 分别代表 这个工人在s1到s2(前闭后闭)的时间里加工了X件小工具

    下一行给出这X件小工具的种类

  要求的是每件工具的加工时间 (唯一解:输出各个时间;无解:Inconsistent data.;多个解:Multiple solutions.)

可以列出同余方程组:∑(ai*xi)≡T(mod 7)

          (ai是此人加工第i件物品的个数,xi是第i件物品加工所需的时间,T是此人干活的时间)

     这样列出m个同余方程 组成方程组 用高斯消元

比如第一个案例:

2 3
2 MON THU
1 2
3 MON FRI
1 1 2
3 MON SUN
1 2 2

可以列出方程组:   1*x0+1*x1≡4(mod 7)
           2*x0+1*x1≡5(mod 7)
           1*x0+2*x1≡7(mod 7)
      1 1 4       1 1 4       1 0 1      2 1 5   →  1 0 1   →  0 1 3      1 2 7       0 1 3       0 0 0 

即得 x0=1,x1=3由题意 每种工具的加工时间为3到9天故 x0=8,x1=3解毕

下面是代码:

有mod就会有要求逆元两种求逆元的方法

1. extend gcd注意得到的x可能为负 要x=(x%mod+mod)%mod;
 1 void ex_gcd(int a, int b, int &x, int &y)
 2 {
 3     if(b)
 4     {
 5         ex_gcd(b, a%b, x, y);
 6         int tmp=x;
 7         x=y;
 8         y=tmp-(a/b)*y;
 9     }
10     else
11     {
12         x=1, y=0;
13         return ;
14     }
15 }

2.inverse element

注意  只适用于a<b 并且 ab互质

1 int inv(int a, int b)
2 {
3     return a==1? 1:inv(b%a, b)*(b-b/a)%b;
4 }

此题还有一法不求逆元:

即 把被除数不断加上mod 直到它能被除数整除为止

 1 while(tmp%a[i][i])
 2      tmp+=mod;
 3 x[i]=(tmp/a[i][i])%mod;
 4
 5 与以下等价
 6
 7 int xx, yy;
 8 ex_gcd(a[i][i], mod, xx, yy);
 9 xx=(xx%mod+mod)%mod;
10 x[i]=(tmp*xx)%mod;
11
12 与以下等价
13
14 x[i]=(tmp*inv(a[i][i], mod))%mod;

完整代码:

  1 const int mod=7;
  2 int gcd(int a, int b)
  3 {
  4     return b==0? a:gcd(b, a%b);
  5 }
  6 int lcm(int a, int b)
  7 {
  8     return a/gcd(a, b)*b;
  9 }
 10 void ex_gcd(int a, int b, int &x, int &y)
 11 {
 12     if(b)
 13     {
 14         ex_gcd(b, a%b, x, y);
 15         int tmp=x;
 16         x=y;
 17         y=tmp-(a/b)*y;
 18     }
 19     else
 20     {
 21         x=1, y=0;
 22         return ;
 23     }
 24 }
 25
 26 int a[300][300];  // 增广矩阵
 27 int x[300];  // 解
 28 int free_x[300]; // 标记是否为自由未知量
 29
 30 int Gauss(int n, int m) // n个方程 m个未知数 即 n行m+1列
 31 {
 32     //转换为阶梯形式
 33     int col=0, k, num=0;
 34     for(k=0;k<n && col<m;k++, col++)
 35     {//枚举行
 36         int max_r=k;
 37         for(int i=k+1;i<n;i++)//找到第col列元素绝对值最大的那行与第k行交换
 38             if(abs(a[i][col])>abs(a[max_r][col]))
 39                 max_r=i;
 40         if(max_r!=k)// 与第k行交换
 41             for(int j=col;j<m+1;j++)
 42                 swap(a[k][j], a[max_r][j]);
 43         if(!a[k][col])// 说明该col列第k行以下全是0了
 44         {
 45             k--;
 46             free_x[num++]=col;
 47             continue;
 48         }
 49         for(int i=k+1;i<n;i++)// 枚举要删除的行
 50             if(a[i][col])
 51             {
 52                 int LCM=lcm(abs(a[i][col]), abs(a[k][col]));
 53                 int ta=LCM/abs(a[i][col]);
 54                 int tb=LCM/abs(a[k][col]);
 55                 if(a[i][col]*a[k][col]<0)
 56                     tb=-tb;
 57                 for(int j=col;j<m+1;j++)
 58                     a[i][j]=((a[i][j]*ta-a[k][j]*tb)%mod+mod)%mod;
 59             }
 60     }
 61
 62     for(int i=k;i<n;i++)
 63         if(a[i][col])
 64             return -1; // 无解
 65
 66     if(k<m)   //m-k为自由未知量个数
 67         return m-k;
 68
 69     //  唯一解 回代
 70     for(int i=m-1;i>=0;i--)
 71     {
 72         int tmp=a[i][m];
 73         for(int j=i+1;j<m;j++)
 74         {
 75             if(a[i][j])
 76                 tmp-=a[i][j]*x[j];
 77             tmp=(tmp%7+7)%7;
 78         }
 79         int xx, yy;
 80         ex_gcd(a[i][i], mod, xx, yy);
 81         xx=(xx%mod+mod)%mod;
 82         x[i]=(tmp*xx)%mod;
 83     }
 84     return 0;
 85 }
 86
 87
 88 void init()
 89 {
 90     memset(a, 0, sizeof(a));
 91     memset(x, 0, sizeof(x));
 92 }
 93
 94 int change(char c1, char c2)
 95 {
 96     if(c1==‘M‘)
 97         return 1;
 98     if(c1==‘T‘ && c2==‘U‘)
 99         return 2;
100     if(c1==‘W‘)
101         return 3;
102     if(c1==‘T‘)
103         return 4;
104     if(c1==‘F‘)
105         return 5;
106     if(c1==‘S‘ && c2==‘A‘)
107         return 6;
108     return 7;
109 }
110
111 char s1[10], s2[10];
112 int main()
113 {
114     int n, m;
115     while(~scanf("%d%d", &n, &m))
116     {
117         if(!n && !m)
118             break;
119         init();
120         for(int i=0;i<m;i++)
121         {
122             int X;
123             scanf("%d%s%s", &X, s1, s2);
124             a[i][n]=((change(s2[0], s2[1])-change(s1[0], s1[1])+1)%mod+mod)%mod;
125             while(X--)
126             {
127                 int t;
128                 scanf("%d", &t);
129                 a[i][t-1]=(a[i][t-1]+1)%mod;
130             }
131         }
132         int t=Gauss(m, n);
133         if(t==-1)
134         {
135             printf("Inconsistent data.\n");
136             continue;
137         }
138         if(t==0)
139         {
140             for(int i=0;i<n;i++)
141                 if(x[i]<=2)
142                     x[i]+=7;
143             for(int i=0;i<n;i++)
144             {
145                 printf("%d", x[i]);
146                 if(i==n-1)
147                     printf("\n");
148                 else
149                     printf(" ");
150             }
151             continue;
152         }
153         printf("Multiple solutions.\n");
154     }
155     return 0;
156 }

POJ 2947

时间: 2024-12-19 01:56:46

[Gauss]POJ2947 Widget Factory的相关文章

POJ2947 Widget Factory

题意 Language:Default Widget Factory Time Limit: 7000MS Memory Limit: 65536K Total Submissions: 7197 Accepted: 2533 Description The widget factory produces several different kinds of widgets. Each widget is carefully built by a skilled widgeteer. The t

[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个制作时间,每段时间制作k个零件,每种零件有一个制作时间,每段时间用Mon到Sun表示,求每个零件的制作时间,还要判断一下多解和无解的情况 思路:对于每段时间列出一个方程,这样一共列出m个方程解n个变元,利用高斯消元去求解,注意每个方程都是MOD 7的,所以在高斯消元过程中遇到除法要求该数字%7的逆元去进行运算 代码: #include <cstdio> #include <cstring> #i

poj 2947 Widget Factory(高斯消元)

description The widget factory produces several different kinds of widgets. Each widget is carefully built by a skilled widgeteer. The time required to build a widget depends on its type: the simple widgets need only 3 days, but the most complex ones

POJ 2947 Widget Factory (高斯消元 判多解 无解 和解集 模7情况)

题目链接 题意: 公司被吞并,老员工几乎全部被炒鱿鱼.一共有n种不同的工具,编号1-N(代码中是0—N-1), 每种工具的加工时间为3—9天 ,但是现在老员工不在我们不知道每种工具的加工时间,庆幸的是还保留着一些对工人制造工具的记录,对于每个老员工,他的记录包括,他开始工作的时间(在某个星期的星期几),被炒鱿鱼的时间(某个星期的星期几),在第几个星期不知道.....在这段时间里,他正好加工了k件物品,给出了这k件物品的编号.我们要做的就是通过这些记录,来确定每种工具的加工时间是多少. 分析: 对

【POJ】2947 Widget Factory(高斯消元)

http://poj.org/problem?id=2947 各种逗啊..还好1a了.. 题意我就不说了,百度一大把. 转换为mod的方程组,即 (x[1,1]*a[1])+(x[1,2]*a[2])+...+(x[1,n]*a[n])=x[1, n+1] (mod m) (x[2,1]*a[1])+(x[2,2]*a[2])+...+(x[2,n]*a[n])=x[2, n+1] (mod m) ... (x[n,1]*a[1])+(x[n,2]*a[2])+...+(x[n,n]*a[n])

poj 2947 Widget Factory

Widget Factory 题意:有n件装饰品,有m组信息.(1 <= n ,m<= 300)每组信息有开始的星期和结束的星期(是在mod 7范围内的)并且还包括num种装饰品的种类(1~n),其中每种装饰品所用的时间3 <= x[i] <= 9;种类的输入可以重复: 思路: 1.根据输入建立增广矩阵a[][],但是在建立和求解的过程中由于是mod意义下的,所以输入的个数和最终所用的时间都要mod 7;(分析可知当个数是7的同余类时,开始星期相同则结束星期也相同) 2.前面几个高

通过扩展jQuery UI Widget Factory实现手动调整Accordion高度

□ 实现Accordion高度一致 <head> <meta name="viewport" content="width=device-width" /> <title>Index</title> <link href="~/Content/jquery-ui.min.css" rel="stylesheet" /> <script src="~/S

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