今年多校比赛第一场遇到了高斯消元,不会,就学习了一下啊。
先说一下学习的博客:
http://www.cppblog.com/menjitianya/archive/2014/06/08/207226.html
http://www.cnblogs.com/kuangbin/category/409938.html
http://hi.baidu.com/czyuan_acm/item/dce4e6f8a8c45f13d7ff8cda
高斯消元主要是解决线性方程组的系数。
算法核心思想:
对于n个方程,m个未知数的方程组,消元的具体步骤如下:
1、枚举第i (0 <= i < n) 行,初始化列为col = 0,每次从[i, n)行中找到第col列中元素绝对值最大的行和第i行进行交换(找到最大的行是为了在消元的时候把浮点数的误差降到最小);
a) 如果第col列的元素全为0,放弃这一列的处理,col+1,i不变,转1);
b) 否则,对于所有的行j (i < j < n),如果a[j][col]不为0,则需要进行消元,以期第i行以下的第col列的所有元素都消为0(这一步就是线性代数中所说的初等行变换,具体的步骤就是将第j行的所有元素减去第i行的所有元素乘上一个系数,这个系数即a[j][col] / a[i][col])。
2、重复步骤1) 直到n个方程枚举完毕或者列col == m。
3、判断解的情况:
a) 如果出现某一行,系数矩阵全为0,增广矩阵不全为0,则无解(即出现[0 0 0 0 0 b],其中b不等于0的情况);
b) 如果是严格上三角,则表明有唯一解;
c) 如果增广矩阵有k (k > 0)行全为0,那么表明有k个变量可以任意取值,这几个变量即自由变量;对于这种情况,一般解的范围是给定的,令解的取值有T个,自由变量有V个,那么解的个数就是 TV。
有的时候需要求最小的解,那么就要状压枚举变元,求最小的解。
下面总结一下,这几天做的题目:
多校联合的题目,通过概率推公式之后得到一个矩阵然后,用高斯消元接出x[0],这是高斯消元解实数的题目在进行行变换的时候与整数不同,直接去掉倍数就行。还有就是高斯消元需要的精度比较高大约是1e-10左右。
POJ 2947 Widget Factory(取模的高斯消元)
高斯消元解决取模问题的题目,应为最后一列都进行了取模的操作,所以当你在解的时候,如果取余不等于0,需要加上x个mod,使得可以整除。
给你一些素数,每次对不同的数取余,其实就是看懂题意,然后一个解决取模问题就行了啊。
POJ 1222 EXTENDED LIGHTS OUT(高斯消元,开关问题)
开关问题,每个点可以和其他相邻的点有关系,如果改动一个点会有其他的点跟着受影响。如果一个点和其他的点有关系他们之间的关系就是1,否则是0。终态是已经给你的,你通过建立的关系就会列出来一个30*30的方程组出来。然后解这个方程组,所得的解就是,开关需不需要动。这里因为开关的状态是只有两种0,1所以可以按照对2取余来解决。
神奇的题目,有很多人暴力搞的。我是建完关系之后用的高斯消元,把找最大的交换改成找任意的交换,就过了。不知道为什么。而且有一些人说这题是模4,不是素数会出现问题。
题目就叫开关问题、、、根据题目建立关系,找出解的个数,如果会有多种解返回个数。无解返回-1.因为每自由元解可以取或不取两种情况,所以共有2^k种解。
这道题目数据很小所以可以dfs,用高斯消元反而麻烦一些了啊。但是可以练习一下高斯消元。这道题目就是类似于开关问题,每个旗子影响其他的旗子。而且终态有两种,全为0,或者全为1。但是这道题目要求输出最少的操作,所以当遇到有多种解的时候你需要枚举一下每个变元,然后求出操作的次数,保存一个操作次数最少的,输出来。
POJ 3185 The Water Bowls(高斯消元,枚举变元)
和1753很像都需要枚举变元,解出来最少的操作次数。
HDU 3976 Electric resistance(高斯消元)
这道题目,上来就是电路图啊,得根据KFC(节点电压法)不是肯德基!通过节点的电流列出关系。然后解出来x[n-1]的结果。
SGU 200. Cracking RSA(高斯消元+高精度)
给出m个整数,因子全部存在于前t个素数。问有多少个子集,他们的乘积是平方数。这道题目感觉不简单,而且思想很好,是个好题啊,标记一下,以后还得多看。
是的乘积是个平方数,那么每一个质数的指数次对2取余都是0。所以我们让最后一列为0,然后解方程组,返回变元的个数所以解的组合有2^k - 1。去掉空集。
SGU 275. To xor or not to xor(高斯消元)
好题啊,而且不简单啊。。。不好理解,看了老长时间才理解一点,智商不够啊、、、
给你n个数字,让你从n个数中,选择一些数,使得异或最大。
要从最高位进行解,我们想要每一位尽可能的为1。所以判断为1是否有解,如果有的话就加上。还有就是一点一点的解方程第一次解第0行,第二次解0~1行,依此类推、、、这样可以使得最高位尽量的为1。
还得继续做题,未完待续。。。。