高斯第一篇
poj1222 EXTENDED LIGHTS OUT
状压枚举法
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 100000 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 int f[10][1<<6],a[8],b[8][8],o[10][1<<6]; 18 char s[8][8]; 19 int main() 20 { 21 int i,j,g,t,kk=0; 22 cin>>t; 23 while(t--) 24 { 25 for(i = 1 ; i <= 5 ; i++) 26 { 27 for(j = 0 ; j < 6 ; j++) 28 { 29 cin>>s[i][j]; 30 b[i][j] = s[i][j]-'0'; 31 } 32 } 33 34 for(i = 0 ; i < (1<<6) ; i++) 35 { 36 for(j = 0 ; j < 6 ; j++) 37 a[j] = b[1][j]; 38 for(g = 0 ; g < 6 ; g++) 39 if((1<<g)&i) 40 { 41 if(g==0) 42 { 43 a[g] = (a[g]+1)%2; 44 a[g+1] = (a[g+1]+1)%2; 45 } 46 else 47 { 48 a[g] = (a[g]+1)%2; 49 a[g-1] = (a[g-1]+1)%2; 50 a[g+1] = (a[g+1]+1)%2; 51 } 52 } 53 54 int tt = 0; 55 for(j = 0 ; j < 6 ; j++) 56 tt+=(1<<j)*a[j]; 57 f[1][tt] = 1; 58 o[1][tt] = i; 59 } 60 for(i = 2; i <= 5 ; i++) 61 { 62 for(j = 0 ; j < (1<<6) ; j++) 63 { 64 if(!f[i-1][j]) continue; 65 for(g = 0 ;g < 6 ; g++) 66 a[g] = b[i][g]; 67 for(g = 0 ; g < 6 ; g++) 68 { 69 if((1<<g)&j) 70 { 71 if(g==0) 72 { 73 a[g] = (a[g]+1)%2; 74 a[g+1] = (a[g+1]+1)%2; 75 } 76 else 77 { 78 a[g] = (a[g]+1)%2; 79 a[g-1] = (a[g-1]+1)%2; 80 a[g+1] = (a[g+1]+1)%2; 81 } 82 } 83 if(o[i-1][j]&(1<<g)) 84 a[g]= (a[g]+1)%2; 85 } 86 int sum=0; 87 for(g = 0 ; g < 6 ; g++) 88 sum+=(1<<g)*a[g]; 89 f[i][sum] = f[i-1][j]; 90 o[i][sum] = j; 91 } 92 } 93 int t = 0; 94 printf("PUZZLE #%d\n",++kk); 95 for(i = 5 ; i >= 1; i--) 96 { 97 t = o[i][t]; 98 for(j = 0 ; j < 6 ; j++) 99 { 100 if(t&(1<<j)) 101 b[i][j] = 1; 102 else 103 b[i][j] = 0; 104 } 105 } 106 for(i = 1 ; i <= 5 ; i++) 107 { 108 for(j = 0 ; j < 5 ; j++) 109 cout<<b[i][j]<<" "; 110 cout<<b[i][5]; 111 cout<<endl; 112 } 113 //puts(""); 114 } 115 return 0; 116 }
高斯消元
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 100000 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 int x[42][42],ans[32]; 18 int gauss() 19 { 20 int i,j,k; 21 for(k = 0 ;k < 30 ; k++)//依次将第k列变换为0 22 { 23 i = k; 24 while(i<30&&x[i][k]==0) i++; 25 if(i!=k)//找出第一个k列不为0的行 与之交换 因为是01 一般的会找出最大的 26 { 27 for(j = 0 ; j <= 30 ; j++) 28 swap(x[k][j],x[i][j]); 29 } 30 //i++; 31 for(i = 0 ;i <30 ; i++)//所有行与第k行进行运算 32 { 33 if(i==k||x[i][k]==0) 34 { 35 continue; 36 } 37 for(j = 0 ;j <= 30 ; j++) 38 { 39 x[i][j]^=x[k][j];//因为01矩阵的特殊性 直接异或就可以了 40 } 41 } 42 } 43 for(i = 0 ;i < 30 ;i++) 44 { 45 if(x[i][30]) 46 { 47 for(j = 0 ; j < 30&&x[i][j]==0 ; j++); 48 if(j==30) return 0; 49 else ans[j] = x[i][30];//也是因为01矩阵的特殊性 免去了解一元方程的麻烦 50 } 51 } 52 return 1; 53 } 54 int main() 55 { 56 int i,j,n,kk=0; 57 cin>>n; 58 while(n--) 59 { 60 memset(ans,0,sizeof(ans)); 61 memset(x,0,sizeof(x)); 62 for(i =0 ;i < 30 ;i++) 63 { 64 scanf("%d",&x[i][30]); 65 } 66 for(i =0 ; i < 30 ;i++)//构造矩阵 行为开关 列为灯 一个开关可以控制5个灯 67 { 68 x[i][i] = 1; 69 if(i>5) x[i][i-6] = 1; 70 if(i%6>0) x[i][i-1] = 1; 71 if(i%6<5) x[i][i+1] = 1; 72 if(i+6<30) x[i][i+6] = 1; 73 } 74 /*for(i = 0 ;i < 30 ;i++) 75 { 76 int tx = i/6; 77 int ty = i%6; 78 x[i][i] = 1; 79 for(j = 0 ; j < 30 ; j++) 80 { 81 int kx = j/6; 82 int ky = j%6; 83 if(abs(tx-kx)+abs(ty-ky)<=1) 84 x[i][j] = 1; 85 } 86 }*/ 87 gauss(); 88 printf("PUZZLE #%d\n",++kk); 89 for(i = 0 ; i < 30 ;i++) 90 { 91 cout<<ans[i]; 92 if((i+1)%6==0) puts(""); 93 else cout<<" "; 94 } 95 } 96 return 0; 97 }
线代都忘干净了。。看了N多博客 及讲解 把上篇最简单的高斯消元入门题搞懂。下面贴几篇讲的不错的博客。
如果对线代没什么概念的话 还是先看下文库的概念及理论 文库讲解
对高斯消元的解析及例题 czyuan原创
高斯消元的模板 比较全的模板 包括无解 有解及多解 模板
然后是对此题详细的讲解 感谢这位 看了他的博客 才明白了这道题 poj1222详解
再大体说一下 这题构造出矩阵 套上模板就可以A了 对于初学,的确不知道怎么构造矩阵,什么叫构造矩阵,先从开关与灯的关系入手,每个开关可以控制5台灯,边上的另算,这样就可以构造出一个开关与灯的01矩阵 A (30*30) 题的目的就是让灯从初始状态变为全0 当然可以逆着来 从0 变为初始状态 所以把初始状态化成一个单位向量 输入为1 B[i] = 1 那就可以列出式子
AX=B X为所求。
这个题与上题类似 不同的地方在于此题可能有多解 需要找出变换次数最小的解 那就要枚举自由元 不知道自由元的话可以看一下上面文库里的概念 每个自由元有两种取值 0,1 每取一次,就会确定方程的一组解 这样从中选出一个最小的 网上大部分题解说是把自由元取为0就可以了 不过没有一篇博客给出证明。。难道这样的结论显而易见? 反正我没证出来,不过我验证了那样写交上去是对的。。还是又用了保险一点的方法,就以普通方法对自由元进行枚举,从中选取最小的。
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 100000 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 int a[230][230],n,free_x[230],x[230]; 18 int gauss() 19 { 20 int i,j,k; 21 int m = n*n; 22 int e= 0,g; 23 int num = 0; 24 for(k = 0 ;k < m&&e< m; k++,e++) 25 { 26 i = k; 27 while(i<m&&a[i][e]==0) i++; 28 if(i==m) 29 { 30 k--; 31 free_x[num++] = e; 32 continue; 33 } 34 if(i!=k) 35 { 36 for(j = 0; j<= m ;j++) 37 swap(a[i][j],a[k][j]); 38 } 39 for(i = k+1 ; i < m ;i++) 40 { 41 if(a[i][e]) 42 { 43 for(j = e ;j <= m ;j++) 44 a[i][j]^=a[k][j]; 45 } 46 } 47 } 48 for(i = k ; i < m ;i++) 49 if(a[i][m]) return -1; 50 if(k<m) 51 { 52 int cnt = 0,minz=INF; 53 int tt = m-k; 54 for(i =0 ;i < (1<<tt) ; i++) 55 { 56 cnt = 0; 57 memset(x,0,sizeof(x)); 58 for(j = 0 ;j < tt ; j++) 59 { 60 if(i&(1<<j)) 61 { 62 x[free_x[j]] = 1; 63 cnt++; 64 } 65 } 66 for(j = k-1; j >= 0; j--) 67 { 68 for(g = j ; g < m ;g++) 69 { 70 if(a[j][g]) break; 71 } 72 x[g] = a[j][m]; 73 for(e = g+1 ; e < m ; e++) 74 { 75 if(a[j][e]) 76 x[g]^=x[e]; 77 } 78 cnt+=x[g]; 79 } 80 minz = min(minz,cnt); 81 } 82 return minz; 83 } 84 for(i = m-1 ; i >= 0 ;i--) 85 { 86 x[i] = a[i][m]; 87 for(j = i+1 ;j < m ; j++) 88 if(a[i][j]) 89 x[i] ^= x[j]; 90 91 } 92 int cnt=0; 93 for(i =0 ;i < m ;i++) 94 if(x[i]) cnt++; 95 return cnt; 96 } 97 int main() 98 { 99 int t,i; 100 cin>>t; 101 while(t--) 102 { 103 cin>>n; 104 memset(a,0,sizeof(a)); 105 for(i = 0 ; i < n*n; i++) 106 { 107 char c; 108 cin>>c; 109 if(c=='y') 110 a[i][n*n] = 0; 111 else 112 a[i][n*n] = 1; 113 } 114 for(i = 0; i < n*n ; i++) 115 { 116 a[i][i] = 1; 117 if(i%n>0) a[i-1][i] = 1; 118 if(i%n<n-1) a[i+1][i] = 1; 119 if(i>=n) a[i-n][i] = 1; 120 if(i+n<n*n) a[i+n][i] = 1; 121 } 122 int cnt = gauss(); 123 if(cnt==-1) 124 { 125 puts("inf"); 126 continue; 127 } 128 cout<<cnt<<endl; 129 } 130 return 0; 131 }
求解的个数 因为只能取01 所以无穷解变成了 2^k k为自由元的个数
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 100000 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 int a[32][32],b[32],c[32],n; 18 int gauss() 19 { 20 int i,j,k,g=1; 21 for(k = 1 ; k <= n && g<=n;k++,g++) 22 { 23 i = k; 24 while(i<=n&&a[i][g]==0) i++; 25 if(i>n) 26 { 27 k--; 28 continue; 29 } 30 if(i!=k) 31 { 32 for(j = 1; j <= n+1 ;j++) 33 swap(a[i][j],a[k][j]); 34 } 35 for(i = k+1 ; i <= n ;i++) 36 { 37 if(a[i][g]) 38 { 39 for(j = g ; j <= n+1; j++) 40 a[i][j]^=a[k][j]; 41 } 42 } 43 } 44 for(i = k ; i <= n ;i++) 45 { 46 if(a[i][n+1]!=0) return 0; 47 } 48 return pow(2.0,n+1-k); 49 } 50 int main() 51 { 52 int t,i; 53 cin>>t; 54 while(t--) 55 { 56 memset(a,0,sizeof(a)); 57 cin>>n; 58 for(i = 1; i <= n ;i++) 59 cin>>b[i]; 60 for(i = 1; i <= n ;i++) 61 { 62 cin>>c[i]; 63 b[i] = (c[i]+b[i])%2; 64 a[i][i] = 1; 65 a[i][n+1] = b[i]; 66 } 67 int u,v; 68 while(cin>>u>>v) 69 { 70 if(!u&&!v) break; 71 a[v][u] = 1; 72 } 73 int k = gauss(); 74 if(!k) {puts("Oh,it's impossible~!!");continue;} 75 cout<<k<<endl; 76 } 77 return 0; 78 }
与1681一样 枚举自由元的状态
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 100000 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 int a[230][230],n,free_x[230],x[230]; 18 int gauss() 19 { 20 int i,j,k; 21 int m = n*n; 22 int e= 0,g; 23 int num = 0; 24 for(k = 0 ;k < m&&e< m; k++,e++) 25 { 26 i = k; 27 while(i<m&&a[i][e]==0) i++; 28 if(i==m) 29 { 30 k--; 31 free_x[num++] = e; 32 continue; 33 } 34 if(i!=k) 35 { 36 for(j = 0; j<= m ;j++) 37 swap(a[i][j],a[k][j]); 38 } 39 for(i = k+1 ; i < m ;i++) 40 { 41 if(a[i][e]) 42 { 43 for(j = e ;j <= m ;j++) 44 a[i][j]^=a[k][j]; 45 } 46 } 47 } 48 for(i = k ; i < m ;i++) 49 if(a[i][m]) return -1; 50 if(k<m) 51 { 52 int cnt = 0,minz=INF; 53 int tt = m-k; 54 for(i =0 ;i < (1<<tt) ; i++) 55 { 56 cnt = 0; 57 memset(x,0,sizeof(x)); 58 for(j = 0 ;j < tt ; j++) 59 { 60 if(i&(1<<j)) 61 { 62 x[free_x[j]] = 1; 63 cnt++; 64 } 65 } 66 for(j = k-1; j >= 0; j--) 67 { 68 for(g = j ; g < m ;g++) 69 { 70 if(a[j][g]) break; 71 } 72 x[g] = a[j][m]; 73 for(e = g+1 ; e < m ; e++) 74 { 75 if(a[j][e]) 76 x[g]^=x[e]; 77 } 78 cnt+=x[g]; 79 } 80 minz = min(minz,cnt); 81 } 82 return minz; 83 } 84 for(i = m-1 ; i >= 0 ;i--) 85 { 86 x[i] = a[i][m]; 87 for(j = i+1 ;j < m ; j++) 88 if(a[i][j]) 89 x[i] ^= x[j]; 90 91 } 92 int cnt=0; 93 for(i =0 ;i < m ;i++) 94 if(x[i]) cnt++; 95 return cnt; 96 } 97 int main() 98 { 99 int t,i; 100 cin>>t; 101 while(t--) 102 { 103 cin>>n; 104 memset(a,0,sizeof(a)); 105 for(i = 0 ; i < n*n; i++) 106 { 107 char c; 108 cin>>c; 109 if(c=='y') 110 a[i][n*n] = 0; 111 else 112 a[i][n*n] = 1; 113 } 114 for(i = 0; i < n*n ; i++) 115 { 116 a[i][i] = 1; 117 if(i%n>0) a[i-1][i] = 1; 118 if(i%n<n-1) a[i+1][i] = 1; 119 if(i>=n) a[i-n][i] = 1; 120 if(i+n<n*n) a[i+n][i] = 1; 121 } 122 int cnt = gauss(); 123 if(cnt==-1) 124 { 125 puts("inf"); 126 continue; 127 } 128 cout<<cnt<<endl; 129 } 130 return 0; 131 }
20个方程 与上面的类似 枚举自由元 选取最小的
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 100000 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 int a[22][22],x[22],free_x[22]; 18 int gauss() 19 { 20 int i,j,g=0,k; 21 int num=0; 22 for(k =0 ;k < 20 && g<20; k++,g++) 23 { 24 i = k; 25 while(i<20&&a[i][g]==0) i++; 26 if(i==20) 27 { 28 k--; 29 free_x[num++] = g; 30 continue; 31 } 32 if(i!=k) 33 { 34 for(j =0 ; j <= 20 ; j++) 35 swap(a[i][j],a[k][j]); 36 } 37 for(i = k+1 ; i < 20; i++) 38 { 39 if(a[i][g]) 40 { 41 for(j = g; j <= 20 ; j++) 42 a[i][j]^=a[k][j]; 43 } 44 } 45 } 46 if(k<20) 47 { 48 int cnt=0,minz=INF,tt = 20-k; 49 for(i =0 ; i< (1<<tt) ; i++) 50 { 51 memset(x,0,sizeof(x)); 52 cnt = 0; 53 for(j = 0 ;j < tt ; j++) 54 { 55 if(i&(1<<j)) 56 { 57 cnt++; 58 x[free_x[j]] = 1; 59 } 60 } 61 for(j = k-1 ; j >= 0; j--) 62 { 63 for(g = j ; g < 20 ; g++) 64 if(a[j][g]) break; 65 x[g] = a[j][20]; 66 for(int e = g+1; e < 20 ; e++) 67 if(a[j][e]) 68 x[g]^=x[e]; 69 cnt+=x[g]; 70 } 71 minz = min(minz,cnt); 72 } 73 return minz; 74 } 75 int cnt = 0; 76 for(i = 19 ; i >= 0; i--) 77 { 78 x[i] = a[i][20]; 79 for(j = i+1 ; j < 20 ; j++) 80 x[i]^=x[j]; 81 cnt+=x[i]; 82 } 83 return cnt; 84 } 85 int main() 86 { 87 int i,b; 88 while(cin>>b) 89 { 90 memset(a,0,sizeof(a)); 91 a[0][20] = b; 92 for(i = 1; i < 20 ;i++) 93 { 94 cin>>b; 95 a[i][20] = b; 96 } 97 for(i = 0 ;i < 20 ; i++) 98 { 99 if(i>0) a[i-1][i] = 1; 100 a[i][i] = 1; 101 if(i<19) a[i+1][i] = 1; 102 } 103 int k = gauss(); 104 cout<<k<<endl; 105 } 106 return 0; 107 }
上面几题都是 01 矩阵的一些求解 ,从这题开始就是一些Modp的一些求解 其实也与之类似 参考着最上面的模板理解一下计算方法 这一类的题目都很类似,不是很难
这题有几个需要注意的地方 要看清题目中说的时间要在3-9天内 在截止时间减开始时间的时候需要不断对7取余 计算时也需要不断对7取余 因为需要整数解 在最后求x[i]的时候需要不断+mod来使得最后的解为一个整数 各种细心啊。。
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 100000 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 int a[310][310],x[310],n,m; 18 int judge(char *s) 19 { 20 if(strcmp(s,"MON")==0) return 1; 21 if(strcmp(s,"TUE")==0) return 2; 22 if(strcmp(s,"WED")==0) return 3; 23 if(strcmp(s,"THU")==0) return 4; 24 if(strcmp(s,"FRI")==0) return 5; 25 if(strcmp(s,"SAT")==0) return 6; 26 return 7; 27 } 28 int gcd(int a,int b) 29 { 30 int t; 31 while(b!=0) 32 { 33 t = b; 34 b = a%b; 35 a = t; 36 } 37 return a; 38 } 39 int gauss() 40 { 41 int i,j,k,g=0; 42 for(k = 1 ; k <= m && g <= n;k++,g++) 43 { 44 i = k; 45 int maxz = a[i][g]; 46 for(j = k+1 ; j <= m ;j++) 47 if(a[j][g]>maxz) 48 { 49 maxz = a[j][g]; 50 i = j; 51 } 52 if(a[i][g]==0) 53 { 54 k--; 55 continue; 56 } 57 if(i!=k) 58 { 59 for(j = 1 ; j<= n+1 ;j++) 60 swap(a[i][j],a[k][j]); 61 } 62 for(i = k+1; i <= m ; i++) 63 { 64 if(a[i][g]) 65 { 66 int gc = gcd(a[i][g],a[k][g]); 67 int lm = a[i][g]/gc*a[k][g]; 68 int u1 = lm/a[i][g]; 69 int u2 = lm/a[k][g]; 70 if(a[i][g]*a[k][g]<0) u2 = -u2; 71 for(j = g ; j <= n+1 ; j++) 72 { 73 a[i][j] = ((u1*a[i][j]-u2*a[k][j])%7+7)%7; 74 } 75 } 76 } 77 } 78 for(i = k ; i<= m ; i++) 79 if(a[i][n+1]) return -1; 80 if(k<n+1) return 0; 81 for(i = n ;i >= 1 ;i--) 82 { 83 int s = a[i][n+1]; 84 for(j = i+1 ; j <= n ;j++) 85 { 86 s-=a[i][j]*x[j]; 87 s=(s%7+7)%7; 88 } 89 while(s%a[i][i]!=0) s+=7; 90 x[i] = ((s/a[i][i])%7+7)%7; 91 } 92 return 1; 93 } 94 int main() 95 { 96 int i,j,k; 97 char s1[20],s2[20]; 98 while(scanf("%d%d",&n,&m)&&n&&m) 99 { 100 memset(a,0,sizeof(a)); 101 memset(x,0,sizeof(x)); 102 for(i = 1 ;i <= m ;i++) 103 { 104 scanf("%d %s %s",&k,s1,s2); 105 int t1 = judge(s1),t2 = judge(s2),t; 106 t = (t2-t1+1+7)%7; 107 a[i][n+1] = t; 108 for(j = 1; j <= k ;j++) 109 { 110 int u; 111 cin>>u; 112 a[i][u]++; 113 a[i][u]%=7; 114 } 115 } 116 int k = gauss(); 117 if(k==-1) 118 puts("Inconsistent data."); 119 else if(k==0) 120 puts("Multiple solutions."); 121 else 122 { 123 for(i = 1 ; i < n ;i++) 124 { 125 if(x[i]<3) x[i]+=7; 126 printf("%d ",x[i]); 127 } 128 if(x[i]<3) x[i]+=7; 129 printf("%d\n",x[i]); 130 } 131 } 132 return 0; 133 }
题意看了好久。。题目中给出了一个式子 0=<i<=n-1 aik^i 和 = f(k) k从1取到n n为字符串长度 f(k)用字符串来表示 a-z代表1-26 *代表0
n个方程很好想到 。。写完发现样例过不去,看了下discuss说是什么范德萌行列式,又说挺难得,我以为想错了,看了下题解,发现跟我写的一样,仔细一看不是
a-'a'而是a-'a'+1 细心啊。。。
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 100000 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 int pp[75][75],a[75][75],x[75]; 18 int md; 19 char s[75]; 20 void init(int n) 21 { 22 int i,j; 23 for(i = 1 ; i <= n ; i++) 24 { 25 pp[i][0] = 1; 26 for(j = 1 ; j < n ; j++) 27 pp[i][j] = (pp[i][j-1]*i)%md; 28 } 29 } 30 int gcd(int a,int b) 31 { 32 int t; 33 while(b) 34 { 35 t = b; 36 b = a%b; 37 a = t; 38 } 39 return a; 40 } 41 void gauss(int n) 42 { 43 int k,i,j,g=0; 44 for(k = 0; k < n && g < n ; k++,g++) 45 { 46 i = k; 47 int maxz = a[i][g]; 48 for(j = k+1 ; j < n ;j++) 49 if(maxz<a[j][g]) 50 { 51 maxz = a[j][g]; 52 i = j; 53 } 54 if(a[i][g]==0) 55 { 56 k--; 57 continue; 58 } 59 if(i!=k) 60 { 61 for(j = 0 ;j <= n ;j++) 62 swap(a[i][j],a[k][j]); 63 } 64 for(i = k+1 ; i < n ;i++) 65 { 66 if(a[i][g]) 67 { 68 int gc = gcd(a[i][g],a[k][g]); 69 int lm = a[i][g]/gc*a[k][g]; 70 int t1 = lm/a[i][g]; 71 int t2 = lm/a[k][g]; 72 if(a[i][g]*a[k][g]<0) t2=-t2; 73 for(j = g ; j <= n ;j++) 74 a[i][j] = ((a[i][j]*t1-t2*a[k][j])%md+md)%md; 75 } 76 } 77 } 78 for(i = n-1 ;i >= 0 ;i--) 79 { 80 int s = a[i][n]; 81 for(j = i+1 ; j < n ;j++) 82 { 83 s-=a[i][j]*x[j]; 84 s = (s%md+md)%md; 85 } 86 while(s%a[i][i]!=0) s+=md; 87 x[i] = s/a[i][i]; 88 } 89 //cout<<k<<endl; 90 for(i =0 ; i< n-1 ; i++) 91 printf("%d ",x[i]); 92 printf("%d\n",x[i]); 93 } 94 int main() 95 { 96 int i,j,t,k; 97 cin>>t; 98 while(t--) 99 { 100 cin>>md; 101 cin>>s; 102 k = strlen(s);init(k); 103 memset(a,0,sizeof(a)); 104 memset(x,0,sizeof(x)); 105 for(i = 0 ; i < k ;i++) 106 { 107 if(s[i]!='*') 108 a[i][k] = s[i]-'a'+1; 109 else 110 a[i][k] = 0; 111 } 112 for(i = 1; i <= k; i++) 113 { 114 for(j = 0 ; j < k ;j++) 115 a[i-1][j] = pp[i][j]; 116 } 117 gauss(k); 118 } 119 return 0; 120 }
poj1166 The Clocks 这题其实不想贴的,感觉这题用高斯来解有些问题,4不为素数,计算中模的话解就变了,自己写的高斯死活过不去,参考着discuss中的一个高斯代码改了改,发现只能按他那一种写法可过 ,像计算中不取余,初等行变换的时候找第一个不为0的 ,找最大的进行交换就会错,用最小公倍数算也会错,各种不行啊。。
这题大部分是枚举过的 ,以前USACO上早就刷过,贴个自己改的不成样子的高斯吧
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 100000 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 int a[20][20],x[10],free_x[10],o[10]; 18 int gcd(int a,int b) 19 { 20 int t; 21 while(b) 22 { 23 t = b; 24 b = a%b; 25 a = t; 26 } 27 return a; 28 } 29 void gauss() 30 { 31 int i,j,g=0,k; 32 int num = 0; 33 for(k = 0 ;k < 9 ; k++) 34 { 35 i = k; 36 for(j = k ; j< 9 ; j++) 37 { 38 if(a[j][k]!=0) 39 { 40 i = j; 41 break; 42 } 43 } 44 if(i!=k) 45 { 46 for(j =0 ;j <= 9 ;j++) 47 swap(a[i][j],a[k][j]); 48 } 49 for(i = k+1 ; i < 9 ; i++) 50 { 51 if(a[i][k]) 52 { 53 /*int gc= gcd(a[i][g],a[k][g]); 54 int lm = a[i][g]/gc*a[k][g]; 55 int t1 = lm/a[i][g]; 56 int t2 = lm/a[k][g]; 57 // if(a[i][g]*a[k][g]<0) t2 = -t2;*/ 58 int tt = a[i][k]; 59 for(j = k ; j <= 9 ;j++) 60 { 61 //a[i][j] = a[i][j]*t1-a[k][j]*t2;//)((%4+4)%4;; 62 a[i][j]*=a[k][k]; 63 a[i][j]-=a[k][j]*tt; 64 } 65 } 66 } 67 } 68 for(i = 8 ; i >= 0; i--) 69 { 70 if(a[i][i]) 71 { 72 int s = a[i][9]; 73 for(j = i+1 ; j < 9 ; j++) 74 { 75 s-=a[i][j]*x[j]; 76 77 } 78 s = (s%4+4)%4; 79 for(j = 0 ; j <= 3 ;j++) 80 if(((j*a[i][i])%4+4)%4==s) x[i] = j; 81 /*while(s%a[i][i]!=0) {s+=4;} 82 x[i] = s/a[i][i];//cout<<",";*/ 83 } 84 } 85 for(i =0 ; i< 9 ; i++) 86 x[i] = (x[i]%4+4)%4; 87 int tk = 0; 88 for(i = 0 ;i < 9 ; i++) 89 { 90 while(x[i]) 91 { 92 if(tk) printf(" "); 93 tk++; 94 printf("%d",i+1); 95 x[i]--; 96 } 97 } 98 puts(""); 99 } 100 int main() 101 { 102 int i,b,j; 103 104 while(cin>>b) 105 { 106 memset(x,0,sizeof(x)); 107 memset(a,0,sizeof(a)); 108 for(i = 0 ; i < 9 ; i++) 109 { 110 switch(i) 111 { 112 case 0: a[0][i] = a[1][i] = a[3][i] = a[4][i] = 1;break; 113 case 1: a[0][i] = a[1][i] = a[2][i] = 1;break; 114 case 2: a[1][i] = a[2][i] = a[4][i] = a[5][i] = 1;break; 115 case 3: a[0][i] = a[3][i] = a[6][i] = 1;break; 116 case 4: a[1][i] = a[3][i] = a[4][i] = a[5][i] = a[7][i] = 1;break; 117 case 5: a[2][i] = a[5][i] = a[8][i] = 1;break; 118 case 6: a[3][i] = a[4][i] = a[6][i] = a[7][i] = 1;break; 119 case 7: a[6][i] = a[7][i] = a[8][i] = 1;break; 120 case 8: a[4][i] = a[5][i] = a[7][i] = a[8][i] = 1;break; 121 } 122 } 123 a[0][9] = (4-b)%4; 124 for(i = 1; i < 9 ; i++) 125 { 126 cin>>b; 127 a[i][9] = (4-b)%4; 128 } 129 gauss(); 130 } 131 return 0; 132 }