Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 1152    Accepted Submission(s): 471
Special Judge


Problem Description
Gambler Bo is very proficient in a matrix game.

You have a M times.
 

 

Input
First line, an integer 30, the matrix is random and guarantee that there is at least one operation solution.
 

 

Output
For each test, first line contains an integer ) describing the operation cell.

The answer may not be unique, you can output any one.
 

 

Sample Input
2 2 3 2 1 2 0 2 0 3 3 1 0 1 0 1 0 1 0 1
 

 

Sample Output
1 1 2 5 1 1 1 3 2 2 3 1 3 3
 

 

Author
绍兴一中
 

 

Source
 

 

Recommend
wange2014

 


gauss消元的mod 3 版本,把n*m个格子上的操作全部变成列向量,共n*m个,每个列向量有n*m个元素,做一遍gauss消元就能解出。

另:优化后因为第i行的状态可以由i+1行确定,所以能建立m个方程,每个方程 M 个变量进行高斯消元,解出解后代回去得到每个元素应该被操作的次数。详见

传送门

我的裸gauss消元代码如下:

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<cmath>
  6 #define clr(x) memset(x,0,sizeof(x))
  7 #define clrdown(x) memset(x,-1,sizeof(x))
  8 #define maxn 910
  9 using namespace std;
 10 int A[maxn][maxn];
 11 int free_x[maxn];
 12 int x[maxn];
 13 int mov[4][2]={0,1,0,-1,1,0,-1,0};
 14 void init(int n,int m);
 15 void gauss(int n,int m);
 16 void print(int n,int m);
 17 int exgcd(int a,int b,int &x,int &y);
 18 int lcm(int a,int b);
 19 int gcd(int a,int b);
 20 int main()
 21 {
 22     int T,p,num,n,m;
 23     scanf("%d",&T);
 24     while(T--)
 25     {
 26         scanf("%d%d",&n,&m);
 27         init(n,m);
 28         gauss(n*m,n*m);
 29         print(n,m);
 30     }
 31     return 0;
 32 }
 33 void print(int n,int m)
 34 {
 35     int sum=0;
 36     for(int i=0;i<n*m;i++)
 37         sum+=x[i];
 38     printf("%d\n",sum);
 39     for(int i=0;i<n;i++)
 40         for(int j=0;j<m;j++)
 41             while(x[i*m+j]>0)
 42             {
 43                 printf("%d %d\n",i+1,j+1);
 44                 x[i*m+j]--;
 45             }
 46     return ;
 47 }
 48 void init(int n,int m)
 49 {
 50     int t;
 51     clr(A);
 52     for(int i=0;i<n;i++)
 53         for(int j=0;j<m;j++)
 54         {
 55             t=i*m+j;
 56             A[t][t]=2;
 57             for(int k=0;k<4;k++)
 58                 if(i+mov[k][0]>=0 && i+mov[k][0]<n && j+mov[k][1]>=0 && j+mov[k][1]<m)
 59                     A[(i+mov[k][0])*m+j+mov[k][1]][t]=1;
 60         }
 61     t=n*m;
 62     for(int i=0;i<n;i++)
 63         for(int j=0;j<m;j++)
 64         {
 65             scanf("%d",&A[i*m+j][t]);
 66             A[i*m+j][t]=(3-A[i*m+j][t])%3;
 67         }
 68     clrdown(x);
 69     clr(free_x);
 70 }
 71 void gauss(int n,int m)
 72 {
 73 //    for(int i=0;i<n;i++)
 74 //    {
 75 //       for(int j=0;j<=m;j++)
 76 //           printf("%d ",A[i][j]);
 77 //       printf("\n");
 78 //    }
 79     int k,col,num=0,max_r,dou,max_x,LCM,ta,tb;
 80     for(k=0,col=0;k<n && col<m;k++,col++)
 81     {
 82         max_r=k;
 83         max_x=abs(A[k][col]);
 84         for(int i=k+1;i<n;i++)
 85             if(max_x<abs(A[i][col]))
 86             {
 87                 max_x=abs(A[i][col]);
 88                 max_r=i;
 89             }
 90         if(max_r!=k)
 91         {
 92             for(int j=col;j<=m;j++)
 93                 swap(A[k][j],A[max_r][j]);
 94         }
 95         if(A[k][col]==0)
 96         {
 97             k--;
 98             free_x[num++]=col;
 99             continue;
100         }
101         for(int i=k+1;i<n;i++)
102         if(A[i][col])
103         {
104             LCM=lcm(A[k][col],A[i][col]);
105             ta=LCM/A[i][col];
106             tb=LCM/A[k][col];
107             for(int j=col;j<=m;j++)
108             {
109                     A[i][j]=((A[i][j]*ta-A[k][j]*tb)%3+3)%3;
110             }
111         }
112     }
113     int temp;
114     for(int i=0;i<num;i++)
115         x[free_x[i]]=0;
116     int  xi,yi;
117     for(int i=k-1,c=m-1;i>=0;c=m-1,i--)
118     {
119         temp=A[i][m];
120         while(x[c]!=-1)
121         {
122             if(A[i][c])
123                 temp=((temp-(x[c]*A[i][c])%3)%3+3)%3;
124             c--;
125         }
126         exgcd(A[i][c],3,xi,yi);
127         xi=(xi%3+3)%3;
128         x[c]=(temp*xi%3+3)%3;
129     }
130 //    for(int i=0;i<n;i++)
131 //    {
132 //        for(int j=0;j<=m;j++)
133 //            printf("%d ",A[i][j]);
134 //        printf("\n");
135 //    }
136 //    for(int i=0;i<m;i++)
137 //        printf("%d ",x[i]);
138     return ;
139 }
140 int exgcd(int a,int b,int &x,int &y)
141 {
142     if(b==0)
143     {
144         x=1;
145         y=0;
146         return a;
147     }
148     else
149     {
150         int r=exgcd(b,a%b,y,x);
151         y-=x*(a/b);
152         return r;
153     }
154 }
155 int gcd(int a,int b)
156 {
157     int c;
158     while(b!=0)
159     {
160         c=a%b;
161         a=b;
162         b=c;
163     }
164     return a;
165 }
166 int lcm(int a,int b)
167 {
168     return a/gcd(a,b)*b;
169 }

 同样的,poj2947: 【传送门

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<cmath>
  6 #define clr(x) memset(x,0,sizeof(x))
  7 #define clrdown(x) memset(x,-1,sizeof(x))
  8 #define maxn 310
  9 #define maxm 310
 10 #define mod 7
 11 using namespace std;
 12 int A[maxn][maxm];//Gauss消元的增广矩阵
 13 int x[maxm];//整数解集
 14 char week[7][10] = {"MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"};
 15 char s1[10],s2[10];
 16 void init(int n,int m);//矩阵初始化操作
 17 int gauss(int n,int m);//gauss消元部分
 18 int exgcd(int a,int b,int &x,int &y);//扩展欧几里得求逆元,对于模mod的矩阵除法需要
 19 int lcm(int a,int b);
 20 int gcd(int a,int b);
 21 int findnum(char *s);
 22 int main()
 23 {
 24     int n,m,p;
 25     while(scanf("%d%d",&n,&m) && n && m)
 26     {
 27         init(n,m);
 28         p=gauss(m,n);
 29         if(p==-1)
 30             printf("Inconsistent data.\n");
 31         if(p==-2)
 32             printf("Multiple solutions.\n");
 33         if(p==0)
 34         {
 35             for(int i=0;i<n;i++)
 36                printf("%d%c", x[i], i == n-1 ?'\n':' ');
 37         }
 38     }
 39     return 0;
 40 }
 41 //读入增广矩阵
 42 void init(int n,int m)
 43 {
 44     clr(A);
 45     int p,ct;
 46     for(int i=0;i<m;i++)
 47     {
 48         scanf("%d%s%s",&p,&s1,&s2);
 49         A[i][n]=((findnum(s2)-findnum(s1)+1)+mod)%mod;
 50         for(int j=0;j<p;j++)
 51         {
 52             scanf("%d",&ct);
 53             A[i][ct-1]++;
 54             A[i][ct-1]=A[i][ct-1]%mod;
 55         }
 56     }
 57     clrdown(x);
 58     return ;
 59 }
 60 int gauss(int n,int m)
 61 {
 62     int k,col,max_r,dou,max_x,LCM,ta,tb;
 63 //k为当前操作行,col为操作主元素所在列
 64     for(k=0,col=0;k<n && col<m;k++,col++)
 65     {
 66         //若A[K][col]不为col列最大,则将k行与k+1到n-1行中A[i][col]绝对值最大的行交换
 67         max_r=k;
 68         max_x=A[k][col];
 69         for(int i=k+1;i<n;i++)
 70             if(max_x<A[i][col])
 71             {
 72                 max_x=A[i][col];
 73                 max_r=i;
 74             }
 75         if(max_r!=k)
 76         {
 77             for(int j=col;j<=m;j++)
 78                 swap(A[k][j],A[max_r][j]);
 79         }
 80         //若k到n-1行A[i][col]全为0,则主元素指向当前行下一列的元素
 81         if(A[k][col]==0)
 82         {
 83             k--;
 84             //自由变元为当前col
 85             continue;
 86         }
 87         for(int i=k+1;i<n;i++)
 88         if(A[i][col])
 89         {
 90             LCM=lcm(A[k][col],A[i][col]);
 91             ta=LCM/A[i][col];
 92             tb=LCM/A[k][col];
 93             for(int j=col;j<=m;j++)
 94             {
 95                  A[i][j]=((A[i][j]*ta-A[k][j]*tb)%mod+mod)%mod;
 96             }
 97         }
 98     }
 99     for(int i=k;i<n;i++)
100         if(A[i][m]!=0)
101             return -1;
102     if(m-k>0) return -2;
103     int  xi,yi,temp;
104     for(int i=k-1,c=m-1;i>=0;c=m-1,i--)
105     {
106         temp=A[i][m];
107         while(x[c]!=-1)
108         {
109             if(A[i][c])
110                 temp=((temp-x[c]*A[i][c])%mod+mod)%mod;
111             c--;
112         }
113         temp=(temp%mod+mod)%mod;
114         exgcd(A[i][c],mod,xi,yi);
115         xi=(xi%mod+mod)%mod;
116         x[c]=((temp*xi)%mod+mod)%mod;
117         if(x[c]<3) x[c]+=mod;
118     }
119     return 0;
120 }
121 int exgcd(int a,int b,int &x,int &y)
122 {
123     if(b==0)
124     {
125         x=1;
126         y=0;
127         return a;
128     }
129     else
130     {
131         int r=exgcd(b,a%b,y,x);
132         y-=x*(a/b);
133         return r;
134     }
135 }
136 int gcd(int a,int b)
137 {
138     int c;
139     while(b!=0)
140     {
141         c=a%b;
142         a=b;
143         b=c;
144     }
145     return a;
146 }
147 int lcm(int a,int b)
148 {
149     return a/gcd(a,b)*b;
150 }
151 int findnum(char *s)
152 {
153     for(int i=0;i<mod;i++)
154     {
155         if(strcmp(s,week[i])==0)
156             return i;
157     }
158 }
Gauss消元

相关文章: