题解 UVA1564 【Widget Factory】
前置题目
分析
我们先建立每个 string
星期对应的 int
类型,可以写一个 函数来实现:
int day(string s)
{
if(s=="MON")
return 1;
if(s=="TUE")
return 2;
if(s=="WED")
return 3;
if(s=="THU")
return 4;
if(s=="FRI")
return 5;
if(s=="SAT")
return 6;
if(s=="SUN")
return 7;
}
设第 种零件的生产天数为 天,第 条记录用了 天,第 条记录的第 种零件生产了 个。
显然 , 可以通过边输入边统计得到:
int k,x;
string S,T;
for(int i=1;i<=m;i++)
{
cin>>k>>S>>T;
b[i]=day(T)-day(S)+1;
for(int j=1;j<=k;j++)
{
cin>>x;
a[i][x]++;
a[i][x]%=7;
}
}
然后可以得出同余方程组:
接下来就可以套高斯消元模板,但是,先看下咱家祖传的高斯消元消去别的方程的系数时的做法:
double z=a[j][i]/a[i][i];
for(int k=i;k<=n;k++)
a[j][k]-=a[i][k]*z;
b[j]-=b[i]*z;
这时你就会发现题目要求的答案是整数,取模时用了 double
就spfa了,怎么办呢?我们看原来消元时的公式:
等式两边可以同时乘一个不为零的数,为了避免除法,我们在同乘一个 :
整个方程也可以乘 ,这样我们就直接把 赋值为 ( 即可。
最后判断解时会出现 的形式,用扩展欧几里得算法求正整数解即可。
代码
#include<bits/stdc++.h>
using namespace std;
const int N=310;
int n,m,a[N][N],b[N];
//日期转换
int day(string s)
{
if(s=="MON")
return 1;
if(s=="TUE")
return 2;
if(s=="WED")
return 3;
if(s=="THU")
return 4;
if(s=="FRI")
return 5;
if(s=="SAT")
return 6;
if(s=="SUN")
return 7;
}
//扩展欧几里得算法(exgcd)
int exgcd(int a,int b,int &x,int &y)
{
if(!b)
{
x=1,y=0;
return a;
}
int d=exgcd(b,a%b,x,y);
int z=x;x=y;y=z-y*(a/b);
return d;
}
//高斯消元
void Gauss()
{
int w=0;//主元个数
for(int i=1;i<=n;i++)
{
int tmp=0;//找到一个最大的x[i]项系数不为0的方程
for(int j=w+1;j<=m;j++)
if(a[j][i]&&(!tmp||a[j][i]>a[tmp][i]))
tmp=j;
if(!tmp)
continue;
swap(b[++w],b[tmp]);
for(int j=1;j<=n;j++)
swap(a[w][j],a[tmp][j]);
for(int j=1;j<=m;j++)//消元
if(w^j&&a[j][i])
{
int z=a[j][i];
for(int k=1;k<=n;k++)
a[j][k]=(a[j][k]*a[w][i]-a[w][k]*z)%7;
b[j]=(b[j]*a[w][i]-b[w]*z)%7;
}
}
for(int i=w+1;i<=m;i++)
{
b[i]%=7;//出现左边为0,右边不为零的方程,无解
if(b[i])
{
cout<<"Inconsistent data."<<endl;
return;
}
}
if(w<n)
{
cout<<"Multiple solutions."<<endl;//主元<n有无数个解
return;
}
int x,y,d;
for(int i=1;i<=n;i++)
{
d=exgcd(a[i][i],7,x,y);
if(b[i]%d)
{
cout<<"Inconsistent data."<<endl;//同余方程无整数解
return;
}
else
{
cout<<((x*b[i]/d-3)%7+7)%7+3;//把特解转换为3~9的正整数解
if(i^n)//输出格式
cout<<" ";
else
cout<<endl;
}
}
}
int main()
{
while(cin>>n>>m&&n&&m)
{
int k,x;
string S,T;
memset(a,0,sizeof(a));
for(int i=1;i<=m;i++)//填入方程组系数
{
cin>>k>>S>>T;
b[i]=day(T)-day(S)+1;
for(int j=1;j<=k;j++)
{
cin>>x;
a[i][x]++;
a[i][x]%=7;
}
}
Gauss();
}
return 0;
}
本文作者:luckydrawbox
本文链接:https://www.cnblogs.com/luckydrawbox/p/18526681
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
分类:
题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步