为了做份高斯消元的模版做了这一题,模版来自http://www.cnblogs.com/kuangbin/archive/2012/08/31/2666144.html。 但这份模版中求自由元的部分应该是错误的,从下向上枚举肯定是不对的,比如x+y+z=10,y+z=5,这个方程组中x实际上是确定的,但这份模版会将x识别为不确定元素。
其实本来是想找份要求自由元的题目的,但还没找到。这题是求同余方程组,跟一般的高斯消元差不多,只是要在消元过程中注意模的问题,另外最后答案要通过扩展欧几里德求出。
继续去找要求求自由元的题目。。
1 #include <string.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <algorithm> 5 #define MAXN 320 6 #define MOD 7 7 int n,m,k,tu; 8 char day[][6]={"MON","TUE","WED","THU","FRI","SAT","SUN"},s1[5],s2[5]; 9 int getday(char *s){ 10 for(int i=0;i<7;i++)if(strcmp(day[i],s)==0)return i; 11 return -1; 12 } 13 //高斯消元解同余线性方程组 14 int x[MAXN][MAXN],ans[MAXN],fre[MAXN]; 15 void exgcd(int a,int b,int &x,int &y){ 16 b?(exgcd(b,a%b,y,x),y-=x*(a/b)):(x=1,y=0); 17 } 18 int gcd(int a,int b){ 19 return b==0?a:gcd(b,a%b); 20 } 21 inline int lcm(int x,int y){ 22 return x*y/gcd(x,y); 23 } 24 int gauss(int n,int m){//n行m+1列,方程从0,0~n-1,m-1,第m列是常数 25 memset(ans,0,sizeof ans); 26 memset(fre,0,sizeof fre); 27 int row=0,col=0; 28 for(;row<n&&col<m;col++){ 29 //保证当前行的元素是最大的 30 int maxr=row; 31 for(int i=row+1;i<n;i++)if(abs(x[i][col])>abs(x[maxr][col]))maxr=i; 32 if(maxr!=row)for(int i=0;i<=m;i++)std::swap(x[maxr][i],x[row][i]); 33 if(x[row][col]==0)continue; 34 //将下面全部变为0 35 for(int i=row+1;i<n;i++) 36 if(x[i][col]!=0){ 37 int g=lcm(abs(x[row][col]),abs(x[i][col])),ga=g/x[row][col],gb=g/x[i][col]; 38 if(x[i][col]*x[row][col]<0)ga=-ga; 39 for(int j=col;j<=m;j++){ 40 x[i][j]=(x[i][j]*gb-x[row][j]*ga)%MOD; 41 if(x[i][j]<0)x[i][j]+=MOD; 42 } 43 } 44 row++; 45 } 46 //判断无解(0,0....a) 47 for(int i=row;i<n;i++)if(x[i][m]!=0)return -1; 48 //判断无穷多解,有效方程个数小于未知数数量 49 if(row<m){ 50 return m-row; 51 } 52 //求唯一解 53 for(int i=m-1;i>=0;i--){ 54 int tmp=0,tx,ty; 55 for(int j=i+1;j<m;j++)tmp+=ans[j]*x[i][j],tmp%=MOD; 56 tmp=(x[i][m]-tmp)%MOD; 57 if(tmp<MOD)tmp+=MOD; 58 //用扩展欧几里德求解 59 exgcd(x[i][i],MOD,tx,ty),tx%=MOD; 60 ans[i]=tx*tmp/gcd(x[i][i],MOD); 61 } 62 return 0; 63 } 64 65 int main(){ 66 freopen("test.in","r",stdin); 67 while(scanf("%d%d",&n,&m),n||m){ 68 memset(x,0,sizeof x); 69 for(int i=0;i<m;i++){ 70 scanf("%d%s%s",&k,s1,s2); 71 while(k--){ 72 scanf("%d",&tu),x[i][tu-1]++,x[i][tu-1]%=MOD; 73 } 74 x[i][n]=((getday(s2)-getday(s1)+1)%MOD+MOD)%MOD; 75 } 76 int t=gauss(m,n); 77 if(t==-1)printf("Inconsistent data.\n"); 78 else if(t>0)printf("Multiple solutions.\n"); 79 else if(t==0){ 80 for(int i=0;i<n;i++){ 81 ans[i]=(ans[i]%MOD+MOD)%MOD; 82 if(ans[i]<3)ans[i]+=7; 83 printf("%d%c",ans[i],i==n-1?'\n':' '); 84 } 85 } 86 } 87 return 0; 88 }