其实高斯消元比较简单,而且似乎没有什么卵用,就水一水吧。
先看模板:【模板】高斯消元法
题目描述
给定一个线性方程组,对其求解
输入格式:
第一行,一个正整数
n
n
第二至行,每行
n+1
n
+
1
个整数,为
a1
a
1
,
a2
a
2
⋯an
⋯
a
n
代表一组方程
输出格式:
共
n
n
行,每行一个数,第行为
xi
x
i
(保留2位小数)
如果不存在唯一解,在第一行输出”No Solution”.
输入样例:
3
1 3 4 5
1 4 7 3
9 3 2 2
输出样例:
-0.97
5.18
-2.39
说明
1≤n≤100,|ai|≤104,|b|≤104 1 ≤ n ≤ 100 , | a i | ≤ 10 4 , | b | ≤ 10 4
高斯消元的做法:和我们普通解方程是一样的,只是更为暴力一些,我们每一次找第一位不为0的一个方程然后用它把其它方程中第一位消掉。如果当前位上所有方程都是0,那么跳过这一位,并打上标记。
最后检查所有剩余方程右侧是不是0,如果不是,则无解,如果是且未打标记,则有唯一解,否则有无穷多解。
但对于这道题来说我们只用判断无解和无穷解,所以只要有一位全0就break。而求解的话,因为只有用来消元的方程才会保留那一位的值。最后如果有解,每一个方程只会保留一个变量。我们把系数调整为1输出即可。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int n,m;
double const eps=1e-8;
double a[105][105];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
for(int j=1;j<=n+1;j++)
scanf("%lf",&a[i][j]);
for(int i=1;i<=n;i++)
{
int pos=i;
for(int j=i+1;j<=n;j++)
if(fabs(a[pos][i])<fabs(a[j][i]))
pos=j;
for(int j=1;j<=n+1;j++)
swap(a[i][j],a[pos][j]);
if(fabs(a[i][i])<eps)
{
printf("No Solution");
return 0;
}
for(int j=n+1;j>=i;j--)
a[i][j]=a[i][j]/a[i][i];
for(int j=1;j<=n;j++)
if(j!=i)
for(int k=n+1;k>=i;k--)
a[j][k]=a[j][k]-a[j][i]*a[i][k];
}
for(int i=1;i<=n;i++)
printf("%.2f\n",a[i][n+1]);
}
异或方程组
定义:每一位前系数为1或0,变量只有1或0,把方程的+变成^。
异或方程组的思路是一样的。但是判断解个数有点不同。如果某位全0,则称这一位线性无关,可以任意取1或0,所以解的个数
∗
∗
2,于是解的个数就是,
x
x
表示线性无关的个数。
异或方程组的变形:
把等号去掉,方程变成表达式,求所有表达式的答案的组合数有多少?其实仔细想想这是一个线性基的题,我们把竖着的一列看做一个数,就是求线性基的数有多少,由于线性无关的数不加入线性基,所以我们的答案其实是, x x <script type="math/tex" id="MathJax-Element-562">x</script>表示线性无关的个数。