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,nxn≡5 (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,nxn≡b (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)
am−1,n−1xn−1+am−1,nxn≡b2 (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;
}