Description
The factory is currently in a state of complete chaos: recently, the factory has been bought by a new owner, and the new director has fired almost everyone. The new staff know almost nothing about building widgets, and it seems that no one remembers how many days are required to build each diofferent type of widget. This is very embarrassing when a client orders widgets and the factory cannot tell the client how many days are needed to produce the required goods. Fortunately, there are records that say for each widgeteer the date when he started working at the factory, the date when he was fired and what types of widgets he built. The problem is that the record does not say the exact date of starting and leaving the job, only the day of the week. Nevertheless, even this information might be helpful in certain cases: for example, if a widgeteer started working on a Tuesday, built a Type 41 widget, and was fired on a Friday,then we know that it takes 4 days to build a Type 41 widget. Your task is to figure out from these records (if possible) the number of days that are required to build the different types of widgets.
Input
4 WED SUN
13 18 1 13
Note that the widgeteers work 7 days a week, and they were working on every day between their first and last day at the factory (if you like weekends and holidays, then do not become a widgeteer!).
The input is terminated by a test case with n = m = 0 .
Output
Sample Input
2 3 2 MON THU 1 2 3 MON FRI 1 1 2 3 MON SUN 1 2 2 10 2 1 MON TUE 3 1 MON WED 3 0 0
Sample Output
8 3 Inconsistent data.
Hint
高斯消元解同余方程组,因为是同模一个数,原因是所给出的时间只是每周的星期数,所以我们要模7。实际上就类似于普通的同余高斯方程解方程。对于一条记录,可以列出一条方程(a1x1+a2x2+...+anxn) mod 7 = k 这里需要注意的是系数需要模下7,否则会溢出。然后就是从第一行往下代入消元了,因为是求整数解,所以求一下两个方程要消元的最小公倍数然后再求,消完元后需要重新模7。理所应当的,如果消元过程中出现之下所有式子某项系数都为0,该项未知数就是自由元,但这并不能说明有多解……
这道题比较麻烦的就是区分多解和无解,若m>n则有一些式子是多余的,他们可能造成无解,所以高斯消元消完后应当验证多余式子是否系数全为0,等式右边是否为0
若存在自由元,将会造成一些式子变成多余的式子,我的方法是先求解,然后倒着带入验证
消成 ax mod 7 = k 的时候,枚举一下x,可能会有多解或无解……这个没注意过是否会有这种情况,但还是判断了一下
求解
|(A1X1+A2X2+...+AnXn)% 7 = k1
|(B1X1+B2X2+...+BnXn)% 7 = k2
| ...
|(M1X1+M2X2+...+MnXn)% 7 = km
问这个方程组有没有解?
如果去掉mod7就是一个很赤裸的高斯消元,不过加了以后只要稍微变化下就可以了
我们只要在高斯消元后,最后得出解时把解的值枚举下看看,看看是否有解在去摸后和结果相同
值得注意的几点:
1 对ax前面系数取模对结果没有影响,所以防止溢出还是取吧。。
2 最后枚举时候模要正的
3 方程数和系数不对称
我们用到系数矩阵和增广矩阵:(1)当系数矩阵的秩不等于增广矩阵的秩时就是无解 (2)当系数矩阵的秩=增广矩阵的秩=行列式的行数就有唯一解(3)当系数矩阵的秩=增广矩阵的秩<行列式的行数就有无穷解
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <string>
using namespace std;
int n,m;
string TIME[8]={"","MON","TUE","WED","THU","FRI","SAT","SUN"};
int matrix[310][310],ans[310];
int caldate(string s)
{
for(int i=1;i<=7;i++)
if(s==TIME[i])
return i;
}
int lcm(int A,int B) //计算A与B的最小公倍数
{
int temp=A*B;
int r;
while(B!=0)
{
r=A%B;
A=B;
B=r;
}
return temp/A;
}
void Guass()
{
int row,col,i,j;
for(row=0,col=0;row<m&&col<n;row++,col++) //化简增广矩阵成上三角矩阵
{
for(i=row;i<m;i++)//每次我们都往下挪一行并且以既定列处的元素开始化简
if(matrix[i][col]!=0)
break;
if(i==m) //如果所遍历列的元素都为0则进入下一列,行数不能变
{
row--;
continue;
}
if(i!=row) //交换两行,保证为上三角矩阵
for(j=0;j<=n;j++)
swap(matrix[row][j],matrix[i][j]);
for(i=row+1;i<m;i++)
if(matrix[i][col]!=0)
{
int LCM=lcm(matrix[row][col],matrix[i][col]);
int x1=LCM/matrix[row][col],x2=LCM/matrix[i][col];
for(j=col;j<=n;j++)
matrix[i][j]=((matrix[i][j]*x2-matrix[row][j]*x1)%mod+mod)%mod;
}
}
if(matrix[i][n]!=0)
{
cout<<"Inconsistent data."<<endl;
return;
}
if(row<n) //无穷解
{
cout<<"Multiple solutions."<<endl;
return ;
}
for (i=n-1;i>=0;i--) //唯一解,解矩阵时应该从后往前算
{
int temp=matrix[i][n];
for (j=i+1;j<n;j++)
{
if(matrix[i][j]!=0)
temp=temp-(matrix[i][j]*ans[j]);
}
while(temp%matrix[i][i]!=0)temp+=7;
ans[i]=temp/matrix[i][i];
if(ans[i]<3) while(ans[i]<3) ans[i]+=7;
else if(ans[i]>9) while(ans[i]>9) ans[i]-=7;
for(i=0;i<n;i++)
{
if(i==n-1)
cout<<ans[i]<<endl;
else
cout<<ans[i]<<" ";
}
}
{
while(scanf("%d%d",&n,&m)!=EOF)
{
if(n==0&&m==0) //据题意说当n=0且m=0时结束
break;
memset(matrix,0,sizeof(matrix)); //用来存增广矩阵
memset(ans,0,sizeof(ans)); //用来存解
for(int i=0;i<m;i++) //一共m份档案
{
int k,day,x; //k是每个人干的总件数,day是开始与结束的时间间隔(模7之后),x是部件编号
string st,en; //st是开始干的日子,en是干完的日子
cin>>k>>st>>en;
day=((caldate(en)-caldate(st)+1)%mod+mod)%mod;
for(int j=0;j<k;j++)
{
scanf("%d",&x);
matrix[i][x-1]=(matrix[i][x-1]+1)%mod; //矩阵的前n-1列存储
}
matrix[i][n]=day; //增广矩阵的最后一列(列数为n)的存储
}
Guass(); //高斯定理
}
return 0;
}