现在的位置: 首页 > 综合 > 正文

高斯消元法小结

2019年02月15日 ⁄ 综合 ⁄ 共 2125字 ⁄ 字号 评论关闭
    这几天做了几题高消的题目,于是想写点感悟什么的。
    在进行高斯消元之前,我们一定要构造好我们所需要的增广矩阵,个人认为这是难点。就目前我做到的提来看,一般利用高消来求解的有异或方程组,普通线性方程组,模方程。
模方程:我们要注意消元时的取模,系数也要不断取模。
异或方程,这里有一类典型的开关问题,我们需要把每个开关放在矩阵的每一行,mat[i][j]=1,表示i开关和j开关有关系,若为0则没关系。然后得到的方程形如mat[i][0]*x[0] ^ mat[i][1]^x[1]  ^ mat[i][2]^x[2]^....^mat[i][j]^x[j]=b[i]
高消的时候不一样的地方就在于向下消元的时候是异或运算消去某个变量。

高消模板:
 

//Gauss消元                                                                                                   
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<iostream>
#include<algorithm>

using namespace std;

const int maxn=50;

int mat[maxn][maxn];

bool free_x[maxn];

int x[maxn];

int start[maxn],endd[maxn];

int n;

inline int gcd(int a,int b)
{
int t;
while(b!=0)
{
t=b;
b=a%b;
a=t;
}
return a;
}

inline int lcm(int a,int b)
{
return a/gcd(a,b)*b;
}

int Gauss(int equ,int var)//equ个方程,对应equ行,var个变远,对应var行
{
int i,j,k;
int max_r;//当前列里绝对值最大的那行
int col;//当前处理列
int ta,tb;
int LCM;
int temp,free_index,free_num;
for (int i = 0; i <= var; i++)
{
x[i] = 0;
free_x[i] = 1;
}
col=0;//从第0列开始处理
for(k=0;k<equ && col<var;k++,col++)
{
max_r=k;
for(i=k+1;i<equ;i++)
{
if(abs(mat[i][col]) > abs(mat[max_r][col]))
max_r=i;
}
if(max_r!=k)
{
for(j=k;j<var+1;j++)
swap(mat[max_r][j],mat[k][j]);
}
if(mat[k][col]==0)
{
k--;
continue;
}
for(i=k+1;i<equ;i++)
{
if(mat[i][col]!=0)
{
LCM=lcm(abs(mat[k][col]),abs(mat[i][col]));
ta=LCM/abs(mat[i][col]);
tb=LCM/abs(mat[k][col]);
if(mat[k][col] * mat[i][col]<0)
tb=-tb;
for(j=col;j<var+1;j++)
mat[i][j]=mat[i][j]*ta-mat[k][j]*tb;
}
}
}
for(i=k;i<equ;i++)
if(mat[i][col] != 0)
return -1;
if(k<var)
{
for(i=k-1;i>=0;i--)
{
free_num=0;
for(j=0;j<var;j++)
{
if(mat[i][j]!=0 && free_x[j])
{
free_num++;
free_index=j;
}
}
if(free_num>1)
continue;
temp=mat[i][var];
for(j=0;j<var;j++)
{
if(mat[i][j]!=0 && j!=free_index)
temp-=x[j]*mat[i][j];
}
x[free_index]=temp/mat[i][free_index];
free_x[free_index]=0;
}
return var-k;
}
for(i=var-1;i>=0;i--)
{
temp=mat[i][var];
for(j=i+1;j<var;j++)
if(mat[i][j]!=0)
temp-=mat[i][j]*x[j];
if(temp%mat[i][i]!=0)
return -2;
x[i]=temp/mat[i][i];
}
return 0;
}

int main()
{
int t;
cin>>t;
while(t--)
{
int n,a,b;
cin>>n;
memset(mat,0,sizeof(mat));
for(int i=0;i<n;i++)
cin>>start[i];
for(int i=0;i<n;i++)
scanf("%d",&endd[i]);
while(cin>>a>>b && (a||b))
mat[b-1][a-1]=1;
for(int i=0;i<n;i++)
{
mat[i][i]=1;
mat[i][n]=start[i]^endd[i];
}
int res=Gauss(n,n);
if(res==-1)
cout<<"Oh,it's impossible~!!"<<endl;
else
cout<<(1 << res)<<endl;
}
return 0;
}


抱歉!评论已关闭.