您的位置:首页 > 其它

POJ 2497 Widget Factory [高斯消元解同余方程组]

2012-09-02 17:48 267 查看
  为了做份高斯消元的模版做了这一题,模版来自http://www.cnblogs.com/kuangbin/archive/2012/08/31/2666144.html。 但这份模版中求自由元的部分应该是错误的,从下向上枚举肯定是不对的,比如x+y+z=10,y+z=5,这个方程组中x实际上是确定的,但这份模版会将x识别为不确定元素。

  其实本来是想找份要求自由元的题目的,但还没找到。这题是求同余方程组,跟一般的高斯消元差不多,只是要在消元过程中注意模的问题,另外最后答案要通过扩展欧几里德求出。

  继续去找要求求自由元的题目。。

  

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#define MAXN 320
#define MOD 7
int n,m,k,tu;
char day[][6]={"MON","TUE","WED","THU","FRI","SAT","SUN"},s1[5],s2[5];
int getday(char *s){
for(int i=0;i<7;i++)if(strcmp(day[i],s)==0)return i;
return -1;
}
//高斯消元解同余线性方程组
int x[MAXN][MAXN],ans[MAXN],fre[MAXN];
void exgcd(int a,int b,int &x,int &y){
b?(exgcd(b,a%b,y,x),y-=x*(a/b)):(x=1,y=0);
}
int gcd(int a,int b){
return b==0?a:gcd(b,a%b);
}
inline int lcm(int x,int y){
return x*y/gcd(x,y);
}
int gauss(int n,int m){//n行m+1列,方程从0,0~n-1,m-1,第m列是常数
memset(ans,0,sizeof ans);
memset(fre,0,sizeof fre);
int row=0,col=0;
for(;row<n&&col<m;col++){
//保证当前行的元素是最大的
int maxr=row;
for(int i=row+1;i<n;i++)if(abs(x[i][col])>abs(x[maxr][col]))maxr=i;
if(maxr!=row)for(int i=0;i<=m;i++)std::swap(x[maxr][i],x[row][i]);
if(x[row][col]==0)continue;
//将下面全部变为0
for(int i=row+1;i<n;i++)
if(x[i][col]!=0){
int g=lcm(abs(x[row][col]),abs(x[i][col])),ga=g/x[row][col],gb=g/x[i][col];
if(x[i][col]*x[row][col]<0)ga=-ga;
for(int j=col;j<=m;j++){
x[i][j]=(x[i][j]*gb-x[row][j]*ga)%MOD;
if(x[i][j]<0)x[i][j]+=MOD;
}
}
row++;
}
//判断无解(0,0....a)
for(int i=row;i<n;i++)if(x[i][m]!=0)return -1;
//判断无穷多解,有效方程个数小于未知数数量
if(row<m){
return m-row;
}
//求唯一解
for(int i=m-1;i>=0;i--){
int tmp=0,tx,ty;
for(int j=i+1;j<m;j++)tmp+=ans[j]*x[i][j],tmp%=MOD;
tmp=(x[i][m]-tmp)%MOD;
if(tmp<MOD)tmp+=MOD;
//用扩展欧几里德求解
exgcd(x[i][i],MOD,tx,ty),tx%=MOD;
ans[i]=tx*tmp/gcd(x[i][i],MOD);
}
return 0;
}

int main(){
freopen("test.in","r",stdin);
while(scanf("%d%d",&n,&m),n||m){
memset(x,0,sizeof x);
for(int i=0;i<m;i++){
scanf("%d%s%s",&k,s1,s2);
while(k--){
scanf("%d",&tu),x[i][tu-1]++,x[i][tu-1]%=MOD;
}
x[i]
=((getday(s2)-getday(s1)+1)%MOD+MOD)%MOD;
}
int t=gauss(m,n);
if(t==-1)printf("Inconsistent data.\n");
else if(t>0)printf("Multiple solutions.\n");
else if(t==0){
for(int i=0;i<n;i++){
ans[i]=(ans[i]%MOD+MOD)%MOD;
if(ans[i]<3)ans[i]+=7;
printf("%d%c",ans[i],i==n-1?'\n':' ');
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: