您的位置:首页 > 其它

高斯消元小结(贴一些模板)

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了,直接跳过就好了。

下面贴一下模板:

高斯消元:

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: