高斯消元小结(贴一些模板)
2015-08-09 22:53
323 查看
依旧是跟着hihocoder学习高斯消元,以前只是知道,并不会写,现在感觉写起来还是比较简单的,其实就是一个线性代数的知识。(我记得今年好像做到过一道高斯消元的题,比较隐蔽的方程组,然后队友最后想到了,然而并没有时间写完,结束以后也并没有补一下高斯消元)。
高斯消元关键就是一个倒三角形吧,然后判断是无穷解,无解,唯一解的的条件就是矩阵的秩与n(元的个数)的关系:
n元方程组 Ax = b 解的情况和R(A),R(A,b),n有关。
无解: R(A) < R(A,b)
唯一解:R(A) == R(A,b) == n
无穷解:R(A) == R(A,b) < n
具体实现方法可以看程序,(然而我觉得hihocoder的伪代码写得很不错)。
然后是异或方程组,这里有一个很重要的异或公式 a xor b == c 等价于 b == a xor c,其实这里很好理解。
异或方程可以表示为 初始状态 xor (a[i][1] * x[1]) xor (a[i][2] * x[2]) xor ... xor (a[i]
*x
) == c[i] 这个时候可以转化成:(a[i][1] * x[1]) xor (a[i][2] * x[2]) xor ... xor (a[i]
*x
) == c[i] xor 初始状态。搞定
异或方程组的消元是利用了 1^1 == 0来做的,但是这个消元的时候要注意,1^0 == 1,也就是在消元的时候不能呆头呆脑地直接搞,遇到这个a[j][i] == 0了,直接跳过就好了。
下面贴一下模板:
高斯消元:
异或方程组:
高斯消元关键就是一个倒三角形吧,然后判断是无穷解,无解,唯一解的的条件就是矩阵的秩与n(元的个数)的关系:
n元方程组 Ax = b 解的情况和R(A),R(A,b),n有关。
无解: R(A) < R(A,b)
唯一解:R(A) == R(A,b) == n
无穷解:R(A) == R(A,b) < n
具体实现方法可以看程序,(然而我觉得hihocoder的伪代码写得很不错)。
然后是异或方程组,这里有一个很重要的异或公式 a xor b == c 等价于 b == a xor c,其实这里很好理解。
异或方程可以表示为 初始状态 xor (a[i][1] * x[1]) xor (a[i][2] * x[2]) xor ... xor (a[i]
*x
) == c[i] 这个时候可以转化成:(a[i][1] * x[1]) xor (a[i][2] * x[2]) xor ... xor (a[i]
*x
) == c[i] xor 初始状态。搞定
异或方程组的消元是利用了 1^1 == 0来做的,但是这个消元的时候要注意,1^0 == 1,也就是在消元的时候不能呆头呆脑地直接搞,遇到这个a[j][i] == 0了,直接跳过就好了。
下面贴一下模板:
高斯消元:
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <stack> #define FOR(i,x,y) for(int i = x;i < y;i ++) #define IFOR(i,x,y) for(int i = x;i > y;i --) #define ll long long #define N 550 #define M 1100 using namespace std; const double eps = 1e-6; int n,m; double a[M] ,c[M],b ,val ; bool zero(double x){ return fabs(x) < eps; } void swap(int i,int j){ FOR(k,1,n+1){ b[k] = a[i][k]; a[i][k] = a[j][k]; a[j][k] = b[k]; } double tem = c[i]; c[i] = c[j]; c[j] = tem; } int guass(){ bool manysolution = false; FOR(i,1,n+1){ bool flag = false; FOR(j,i,m+1){ if(!zero(a[j][i])){ swap(i,j); flag = true; break; } } if(!flag){ manysolution = true; continue; } FOR(j,i+1,m+1){ double tem = a[j][i]/a[i][i]; FOR(k,i,n+1){ a[j][k] = a[j][k] - a[i][k]*tem; } c[j] = c[j] - c[i]*tem; } } FOR(i,1,m+1){ bool flag = true; FOR(j,1,n+1){ if(!zero(a[i][j])){ flag = false; break; } } if(flag && !zero(c[i])){ return -1; } } if(manysolution) return 1; IFOR(i,n,0){ FOR(j,1,i){ double tem = a[j][i]/a[i][i]; FOR(k,1,n+1){ a[j][k] = a[j][k] - a[i][k]*tem; } c[j] = c[j] - c[i]*tem; } val[i] = c[i]/a[i][i]; } return 0; } int main() { //freopen("test.in","r",stdin); while(~scanf("%d%d",&n,&m)){ FOR(i,1,m+1){ FOR(j,1,n+1) scanf("%lf",&a[i][j]); scanf("%lf",&c[i]); } int tem = guass(); if(tem == -1) printf("No solutions\n"); else if(tem == 1) printf("Many solutions\n"); else{ FOR(i,1,n+1){ printf("%d\n",(int)(val[i]+eps)); } } } return 0; }
异或方程组:
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <queue> #include <stack> #define ll long long #define FOR(i,x,y) for(int i = x;i < y;i ++) #define IFOR(i,x,y) for(int i = x;i > y;i --) #define N 35 using namespace std; const double eps = 1e-6; char str[10]; int a ,c ,val ,ans ; void init(){ FOR(i,0,30) c[i] = c[i] ^ 1; memset(a,0,sizeof(a)); FOR(i,0,30){ int u = i / 6, v = i % 6; a[i][i] = 1; int nu,nv; nu = u-1;nv = v; if(nu >= 0 && nu < 5 && nv >= 0 && nv < 6) a[i][nu*6+nv] = 1; nu = u+1;nv = v; if(nu >= 0 && nu < 5 && nv >= 0 && nv < 6) a[i][nu*6+nv] = 1; nu = u;nv = v-1; if(nu >= 0 && nu < 5 && nv >= 0 && nv < 6) a[i][nu*6+nv] = 1; nu = u;nv = v+1; if(nu >= 0 && nu < 5 && nv >= 0 && nv < 6) a[i][nu*6+nv] = 1; } } void swap(int i,int j){ FOR(k,0,30){ int tem = a[i][k]; a[i][k] = a[j][k]; a[j][k] = tem; } int tem = c[i]; c[i] = c[j]; c[j] = tem; } int guass(){ bool manysolutions = false; FOR(i,0,30){ bool flag = false; FOR(j,i,30){ if(a[j][i]){ swap(i,j); flag = true; break; } } FOR(j,i+1,30){ if(!a[j][i]) continue; FOR(k,0,30){ a[j][k] = a[i][k] ^ a[j][k]; } c[j] = c[i] ^ c[j]; } if(!flag){ manysolutions = true; } } FOR(i,0,30){ int flag = true; FOR(j,0,30){ if(a[i][j]) flag = false; } if(flag && c[i]) return -1; } if(manysolutions) return 1; IFOR(i,29,-1){ FOR(j,0,i){ if(!a[j][i]) continue; FOR(k,0,30){ a[j][k] = a[i][k] ^ a[j][k]; } c[j] = c[j] ^ c[i]; } val[i] = c[i]; } return 0; } int main() { //freopen("test.in","r",stdin); while(~scanf("%s",str)){ FOR(i,0,6){ c[i] = str[i] - '0'; } FOR(i,1,5){ scanf("%s",str); FOR(j,0,6){ c[i*6+j] = str[j] - '0'; } } memset(val,0,sizeof(val)); init(); guass(); int cnt = 0; FOR(i,0,30){ if(val[i]) ans[cnt++] = i; } printf("%d\n",cnt); FOR(i,0,cnt){ printf("%d %d\n",(ans[i]/6)+1,(ans[i]%6)+1); } } return 0; }
相关文章推荐
- android引导页的实现
- 第5章
- 我们为什么要使用补码?
- 课后作业07--二分法查找算法代码
- 文件写入或控制台输出显示:"烫烫烫烫"问题解决办法
- 论文注解《Query Languages for Graph Databases》graph数据库查询语法(III)
- mac上安装android studio出现Error:compileSdkVersion android-x requires compiling with JDK 7问题
- java处理高并发高负载的网站的优化方法
- 2维,3维向量单位化
- 关于动态链接库的接口
- (4.1.28.3)第二种方法HttpClient.setCookieStore(mCookieStore)实现的HTTP工具类
- Struts2中的ModelDriven机制及其运用
- ZOJ 3204 Connect them
- BACnetScan读BI多个属性——请求报文和应答报文解析
- Java 使用Charset类解决读入字符乱码问题和控制输出字符编码
- 卡特兰数
- 好用的Markdown编辑器一览
- java的回调函数
- Android FlowLayout
- 一定要知道!好的设计竟能如此重要