rwchen的博客

温故而知新

高斯消元求解线性方程组

  1. 利用初等行变换将方程组变成行阶梯式矩阵 > 1. 交换任意两行 > 2. 将一行乘以一个非零常数 > 3. 将一行的若干倍加到另一行

  2. 得到行阶梯矩阵便可以逐一步求解

  3. 解的结构 \(\begin{cases} 无解 \\ \\ 有解 \begin{cases} 唯一解 \\ \\ 无穷多解 \\ \end{cases}\\ \end{cases}\)

  4. 算法步骤 > 枚举每一列,固定当前列 > 1. 枚举没固定的行,找到当前固定列绝对值最大的那行 > 2. 将当行放到本次要固定行的位置 > 3. 将该行将固定列的值变成1 > 4. 利用当前行将当前行下面的行的固定列值都变成0

  5. 相关例题

883. 高斯消元解线性方程组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <bits/stdc++.h>
using namespace std;

const int N = 110;
const double eps = 1e-8;
double matrix[N][N];

void print(int n) {
for (int i = 1; i <= n; ++i) {
auto &x = matrix[i][n + 1];
if (fabs(x) < eps) x = 0;
printf("%.2lf\n", x);
}
}

int gauss(int n) {
int rank = 1; // 矩阵的秩
// 变行阶梯矩阵
for (int col = 1; col <= n; ++col) { // 枚举列

int row = rank; // 要固定的行
for (int i = row; i <= n; ++i) // 找绝对值最大的列
if (fabs(matrix[i][col]) > fabs(matrix[row][col]))
row = i;

swap(matrix[rank], matrix[row]); // 将该行换过来
row = rank; // 当前操作的行
if (fabs(matrix[row][col]) < eps) continue; // 都是0无法归一

for (int i = n + 1; i > col; --i) matrix[row][i] /= matrix[row][col]; // 归一
matrix[row][col] = 1;

for (int i = row + 1; i <= n; ++i) { // 消元,将该行该列第一个数变成0
const double k = matrix[i][col];
if (fabs(k) < eps) continue; // 已经是0了
for (int j = n + 1; j > col; --j)
matrix[i][j] -= matrix[row][j] * k; // 减去k倍
matrix[i][col] = 0;
}

++rank; // 矩阵的秩+1
}

// cout << rank << '\n';
// for (int i = 1; i <= n; ++i)
// for (int j = 1; j <= n + 1; ++j)
// cout << matrix[i][j] << " \n"[j == n + 1];

if (rank < n + 1) { // 无解或者无穷解
for (int i = rank; i <= n; ++i)
if (fabs(matrix[i][n + 1]) > eps) // 该行的系数都是0,但常数项>0
return -1; // 无解
return 0; // 无穷多解
}

for (int row = n; row; --row) { // 从下往上求解
for (int col = n; col > row; --col) {
matrix[row][n + 1] -= matrix[row][col] * matrix[col][n + 1];
matrix[row][col] = 0;
}
}

return 1; // 唯一解
}

int main() {
int n;

cin >> n;
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n + 1; ++j)
cin >> matrix[i][j];

int f = gauss(n);
if (f == -1) cout << "No solution\n";
else if (f == 0) cout << "Infinite group solutions\n";
else print(n); // unique solution

return 0;
}

作者:rw-chen
链接:https://www.acwing.com/activity/content/code/content/5071614/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

883. 高斯消元解线性方程组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include <iostream>
using namespace std;

const int N = 110;
bool matrix[N][N];

void print(int n) {
for (int i = 1; i <= n; ++i) cout << matrix[i][n + 1] << '\n';
}

int gauss(int n) {
// 求行阶梯矩阵
int rank = 1;
for (int col = 1; col <= n; ++col) {
int row = rank; // 固定的行
for (; row <= n && !matrix[row][col]; ++row); // 找一个1就好

if (row > n || !matrix[row][col]) continue; // 全都是0

swap(matrix[rank], matrix[row]); // 交换
row = rank;


for (int i = row + 1; i <= n; ++i) // 消元
if (matrix[i][col])
for (int j = col; j <= n + 1; ++j)
matrix[i][j] ^= matrix[row][j];

++rank;
}

// for (int i = 1; i <= n; ++i)
// for (int j = 1; j <= n + 1; ++j)
// cout << matrix[i][j] << " \n"[j == n + 1];

if (rank <= n) {
while (rank <= n)
if (matrix[rank++][n + 1] > 0)
return -1; // 无解
return 0; // 多组解
}

for (int row = n; row; --row) {
for (int col = n; col > row; --col) {
matrix[row][n + 1] ^= matrix[row][col] * matrix[col][n + 1];
matrix[row][col] = 0;
}
}

return 1; // 唯一解
}

int main() {
int n;
cin >> n;
for (int i = 1; i <= n; ++i)
for (int j = 1;j <= n + 1; ++j)
cin >> matrix[i][j];

int f = gauss(n);
if (f == 1) print(n);
else if (f == 0) cout << "Multiple sets of solutions\n";
else cout << "No solution\n";

return 0;
}

作者:rw-chen
链接:https://www.acwing.com/activity/content/code/content/5071999/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  1. 时间复杂度\(O(n^3)\) > 枚举列,利用每一行消元,所以\(O(n^3)\)

@date: 2022-11-11

  1. 结构化查询语言(Structured Query Language, SQL)

    1. 数据定义语言(Data Definition Language, DDL), 创建删除数据库、表,修改字段等
    2. 数据操作语言(Data Manipulation Language, DML), CRUD
    3. 数据控制语言(Data Control Language, DCL), 管理用户权限

  2. 控制台常用命令:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    net start mysql80    // 将mysql服务启动(需要管理员权限)cmd指令
    net stop mysql80 // 将mysql服务关闭 cmd指令
    mysql -uroot -proot // 用账号密码登录数据库 cmd指令
    mysqldump -uroot -proot db_name > D:\src.sql // 导出指定数据库里所有表的建表语句 (不包含建立库) cmd指令
    show databases; // 展示当前可用数据库
    use database_name; // 使用某个数据库
    show tables; // 展示当前数据库下的表
    source D:/test.sql // 导入表到当前数据库
    \s // 查看当前状态
    \h // 帮助
    quit // 退出
    ---

  3. 常见关键字(注:MySQL大小写不敏感)

    关键字
    1
    2
    3
    4
    5
    6
    7
    8
    database, databases, table, tabels, create, drop, use, show, desc(describe),
    alter, delete, update, insert, into, set, truncate, select, distinct, from,
    constraint, add, check, as, if, else, elseif, true, false, exists, union,
    unique, index, primary, key, foreign, references, asc(ascend), desc(descend),
    limit, and, or, is, not, where, in, between, null, like, default, group, order,
    by, having, inner, left, right, join, on, cascade, grant, revoke, commit, rollback,
    @, @@, procedure, begin, end, inout, out, call, declare, trigger, before, after,
    ...
    ---

  4. 通配符

    通配符
    1
    2
    % 0个或多个字符
    _ 单字符


  1. 常见SQL(Structured Query Language)语句

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    create database 'database_name'; # 创建数据库,注:一般在引用字段,表名,数据库名时,可以选择性的加符号 `` 

    drop database database_name; # 删除数据库
    drop type_name if exists del_name # typename可以是数据库,表,视图,存储过程等等防止没有删除不了

    show databases; # 展示当前连接下的所有数据库

    use database_name; # 改变当前使用的数据库

    show tables; # 展示当前使用数据库下的所有表

    drop table table_name; # 删除表
    drop table if exists table_name; # 防止表不存在删不了

    create table table_name #创建表
    (
    field_1 int primary key auto_increment, # 设置成主键和自动增长
    field_2 varchar(10) unique, # 设置成无重复字段, varchar必须带长度
    field_3 float default(10.0) not null, # 设置默认值 非空字段
    field_4 blob, # 字段不设置默认值default, 那么默认值就是null
    [constraint key_name] foreign key(field_1) references other_table(field_x)
    # 当前表的field字段,参照外键field_x
    # 注:最后一个语句后面不带','
    # [constraint pk_id] primary key(field1[,...]) 建立联合主键的方法
    # [constraint uk_id] unique(field1[...field2]) 建立联合唯一约束
    # [constraint ck_id] check(field_3 is not null) 等同于上面设置的非空字段
    );

    create table newTable select * from otherTable;
    # 等同于复制表结构和记录, 不想复制记录可以接 where 1+1=10 只要条件表达式的值为false即可不复制记录

    desc table_name; # describe的缩写desc查看表结构

    show create database database_name # 查看建数据库语句
    show create table table_name; # 查看建表语句

    insert into table_name values (null, 'king4', 12, 'dijkstra'); # 向表中插入记录, 这是全部字段都插入

    insert into table_name(field_3, field_1) values (6.66, 12); # 向表中插入记录,自定义要插入记录的字段

    insert into table_name(field_1, field_2d, ...) select field_a, field_b... from other_table;
    # 将其他表中查询的记录入当前表

    select field new_name from table; # 直接紧跟在字段后面,field起别名为new_name

    select field as new_name from table; # 用as给字段field起别名为new_name

    select * from table_name; # *代表所有, 查询所有字段, *可以替换成想要查询的字段,

    select * from table_name where field_1 = 1; # where后面接逻辑表达式构成条件查询

    select field1, field2, ...fieldN from table_name where fieldx like "q_q"
    # 模糊查询fieldx字段长度为2的记录, '_'代表一个字符, '%'代表所有字符

    update table_name set field1 = value, field2 = value, field3 = value, ... [where condition]
    # 修改或更新表中的记录

    delete from table_name [where condition] # 删除表中的记录, 自动递增不会删除

    truncate table_name # 先新建一张结构一样的表,然后删除当前表

    alter table table_name add [column] field_name int null [first|after field_xx]; # 给table_name添加字段

    alter table table_name drop [column] field; # 删除table_name的field字段

    alter table table_name modify field1 bigint... # 修改字段的属性

    alter table table_name change old_field_name new_field_name int... # 修改字段的名称与属性
    %注意区分modify 和 change%

    alter table old_table_name rename to new_table_name; # 重命名表

    alter table add primary key(field[,...]); # 直接添加主键,不起名称

    alter table table_name add constraint pk_name primary key(field);
    # 添加field字段为主键, 并给主键起名为pk_name

    alter table table_name drop primary key; # 删除table_name表的主键

    alter table table_name add [constraint key_name] foreign key (field_1) references other_table(field_x)
    # 给table_name的field_1字段添加的外键为other_table.field_x

    alter table table_name drop constraint fk_name; # 删除约束fk_name
    alter table table_name drop foreign key fk_name; # 删除外键fk_name

    alter table table_name add [constraint key_name] unique(field_2[,...])
    # 给table_name表的field_2字段添加unique约束, unique约束表名该字段不存在重复值但可以为null

    alter table table_name drop constraint unique_key_name; # 删除该约束

    alter table table_name add [constraint ck_name] check(boolean_expression)
    # 给table_name表添加check约束, 删除check约束同删除unique约束

    create index index_name on table_name(field1)
    alter table table_name add index index_name(field1)
    # 给table_name表的field1字段添加索引

    drop index index_name on table_name;
    alter table table_name drop index index_name;
    # 删除索引

    show index in table_name;
    show index from table_name; # 查看索引

    select field1, field2, ... from table1
    union [all | distinct] # 默认distinct去重, all则不会去除重复记录
    select field1, field2, ... from table2;
    # 连接2个以上的结果集结合到一起,默认(distinct)去除重复记录,注意选中的列数要一致

    select fieldd1, field2, ... from table_name order by field1 [asc[desc], [field2 [asc, [desc]]
    # 选择关键字进行排序, asc(ascend升序), desc(descend降序)

    select field_name, function(field_name) from table_name
    where condition # 筛选条件
    group by field_name # 分组求max, min, avg, sum, age等等

    select coalesce(a, b, c, ...);
    # 从前往后选第一个不为null的, 如果找不到返回null

    select coalesce(name, 'total'), count(name) from table_name group by name with rollup;
    # with rollup 可以实现在分组统计数据基础上再进行相同的统计(sum,avg, count, age…)

    select field1, function(field1) from stdudent
    where expression1
    group by field1
    having expression2;
    # having类似于where,但where用于分组前对满足条件的记录做筛选,而having是分组后筛选
    # 例如要按部门分组查询年龄处于50~60,且这组50~60间的平均年龄小于等于55

    select * from table1 join table2; # 两个表做笛卡尔积
    select * from table1, table2; # 同上

    select * from table1 inner join table2 on expression;
    # inner join(内连接) 通常省略为join, on 后面跟的是连接条件,只有满足条件时,才会将对应的记录示出来

    select * from table1, table2 where expression;
    # 当前上面简单的连接也可以用条件查询的方式完成

    select * from left_table left join right_table on expression;
    # left join (左连接) 左表里面选出的字段都会显示出来,右表选的字段满足连接条件才显示,不满足则显示为null

    select * from left_table right join right_table on expression;
    # right join (右连接) 右表里面选出的字段都会显示出来,左表选的字段满足连接条件才显示,不满足则显示为null

    select null = null; # 结果为空null
    select null != null; # 结果为空null
    select 1 == null; # 结果为空null
    select 1 != null; # 结果为空null
    select null is null; # 1
    select null is not null; # 0
    select null <=> null; # 1
    select 1 <=> null; # 0
    select 1 <=> 2; # 0
    select 1 <=> 1; # 1
    # 因为null的情况特殊,所以对null进行比较运算时,一般使用用is null, is not null, <=> 进行

    create view view_name as select ...; # 创建视图

    alter view view_name as select ...; # 修改视图
    # 视图的其他操作几乎都合表一样,但视图本质是一段逻辑sql,真正的记录都来源于表

    @ 用户变量
    @@ 系统变量

    select @@autocommit; # 查看系统变量autocommit的值
    set @@autocommit = 0; # 设置自动添交事务开启
    set @@autocommit = 1; # 设置自动添交事务关闭
    begin; # 开启事务,当进行增删改时,不会自动提交
    commit; # 手动提交事务
    rollback; # 回滚,将没有提交的事务撤销

    create user 'user_name'@'localhost' IDENTIFIED by '123'; #创建用户

    grant all on db_name.table_name on 'username'@'host' identified by 'password';
    # 创建用户并赋予权限

    grant select, update on *.* to 'test_user'@'localhost' identified by 'pwd';
    # 用户test_user对所有的数据有查询和更新权限,并授于对所有数据表的select和update权限

    grant all on *.* to 'root'@'localhost'
    # 给用户所有权限

    revoke all on *.* from 'user '@'localhost';
    # 移除用户所有权限

    # 存储过程就相当于把sql语句封装成函数

    create procedure p_name(in p1 int, out p2 int, inout p3 int)
    # 声明存储过程

    begin ... end
    # 存储过程的开始和结束

    set @var = 20;
    # 给变量赋值

    declare variable datatype[default value]
    # 局部变量定义

    drop procedure pcd_name;
    # 删除存储过程

    # 触发器...

  2. 聚合函数

    1
    max, min, avg, sum, count

  3. 常用函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    concat(s1, s2[,...])    # 将字符串按顺序连接在一起
    coalesce(a, b, c, ...) # 从前往后选第一个不为null的, 如果找不到返回null
    ifnull(a, b) # 当 a <=> null 时 返回 b
    ceil(x) # x向上取整
    floor(x) # x向下取整
    mod(a, b) # a % b
    lower('CodeBugZERO') # 转小写, codebugzero
    upper('rw-chen') # 转大写, RW-CHEN
    lpad(str, n, t) # 当str长度不足n位时,用t依次补齐
    rpad(str, n, t) # 同上, 换成右边补
    trim(str) # 去掉str首尾的空格
    substring(str, pos, k) # 从字符串的pos位开始取k位,注str从1开始
    rand(seed) # 返回一个01之间的随机数, seed为种子, 可以不填
    round(number, k) # 给number表示保留k位小数 四舍五入

  4. truncate, delete, drop区别与联系 > truncate只能用于表,语法为 truncate table table_name 或者 truncate table_name,执行truncate需要drop权限,执行后不能回滚,其本质是新建一张和当前结构相同的表,不插入记录,然后将当前表删除,truncate和drop都是DDL语句执行后都不能回滚,delete是DML语句可回滚,truncate会清空表中的所有行,但表结构及其约束、索引等保持不变;drop会删除所有, truncate会重置自增列,delete不会, truncate不会激活与表有关的删除触发器,delete可以,truncate后会使表和索引所占用的空间会恢复到初始大小;delete操作不会减少表或索引所占用的空间,drop语句将表所占用的空间全释放掉。

  5. 事务四大特性 > 原子性,一致性,隔离性,持久性

  6. 三大范式 > 第一范式要求数据库表的每一列都是不可分割的基本数据项,同一列中不能有多个值 > 第二范式要求实体中每一行的所有非主属性都必须完全依赖于主键,非主属性依赖主键 > 第三范式要求实体中的属性不能是其他实体中的非主属性,属性不依赖于其他非主属性****

Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.

Quick Start

Create a new post

1
$ hexo new "My New Post"

More info: Writing

Run server

1
$ hexo server

More info: Server

Generate static files

1
$ hexo generate

More info: Generating

Deploy to remote sites

1
$ hexo deploy

More info: Deployment

0%