书名:算法竞赛-入门经典 第2版
作者:刘汝佳
类别:读书笔记
文章目录
前言
前言之中比较重要的是作者对整本书的架构安排:
- 第一部分是语言篇(第1-4章)
- 第二部分是算法篇(第5-8章)
- 第三部分是竞赛篇(第9-11章)
- 全新的第12章是在《算法竞赛入门经典----训练指南》的基础上补充少量知识与大量精彩例题
第1章 程序设计入门
1.1 算术表达式
#include <stdio.h>
#include <math.h>
int main(int argc, const char * argv[]) {
printf("%d\n", 1+2);
return 0;}
Experiment 1 - 4:
Expression | output |
---|---|
1+2 | 3 |
3-4 | -1 |
5*6 | 30 |
8/4 | 2 |
8/5 | 1 |
-8/5 | -1 |
此处需要注意整数相除可能会有 Truncation 的现象出现。
#include <stdio.h>
#include <math.h>
int main(int argc, const char * argv[]) {
printf("%1f\n", 8.0/5.0);
return 0;}
Experiment 5 - 7:
Statement | output |
---|---|
printf("%.1f\n", 8.0/5.0) | 1.6 |
printf("%.2f\n", 8.0/5.0) | 1.60 |
printf("%.1f\n", 8/5) | 0.0 |
printf("%d\n", 8.0/5.0) | -272632504 |
尽管已经学过C很久了,我也没有想到实验7居然会得出这个结果,这是为什么呢?
Learning Points:
- Output integers by %d, output real numbers by %f
*f stands for floating point - Integer/Integer = Integer; Floating Point/ Floating Point = Floating Point
1.2 变量及其输入
Learning Points:
语法相关:
- How to read keyboard input?
scanf 中的占位符(例如%d, %f)和变量应该一一对应,而且每个变量之前必须要加“&”。 - 尽量用const 声明常数。
竞赛相关:
- 在竞赛当中,输入前不要打印提示信息,输出后应该立即终止程序。
- 每一行输出都应该以回车符 \n 结束,包括最后一行。除非特别说明,行首不应该有空格。
有关赋值(Assignment) 和 printf 函数的使用不再赘述。
1.3 顺序结构程序设计(Sequential Program)
如何交换两个变量(swapping)?
- 三变量法
- 算术法 (第8页程序1-9)
- 直接输入输出
Learning Points:
竞赛相关:
- 可以用手工模拟的方式理解程序的执行方式,那么模拟的具体写什么呢?重点在于记录每条语句执行之后各个变量的值。
1.4 分支结构程序设计(Branching)
Learning Points:
语法相关:
- if 语句的基本格式为 (只有一条语句时,花括号“{ }”可以省略):
if (condition) { statement 1; ... } else { statement 2. ... }
condition
可以是逻辑表达式(logical expression) 也可以是整数值。注意condition是整数值的时候,0=false
, 其他值=true
。- 如果有多个并列、情况不交叉的
condition
需要一一处理,可以用else if 语句。 - 注释可以使用
//
或者/* */
竞赛相关:
- 在竞赛当中,我们设计的程序应该对任何输入都有效,而不仅仅是样例数据。Make sure program works beyond given test cases.
1.5 注解与习题
1.5.1 C语言、C99、C11 以及其他
C语言标准:设计之初是为了防止同样的程序被不同的编译器编译成截然不同的指令
读者需要注意的是,应当把前4章的内容当成是在学习C++当中与C相兼容的部分。
1.5.2 数据类型与输入格式
#include <stdio.h>
#include <math.h>
int main(int argc, const char * argv[]) {
int a = 11111*11111;
printf("%d\n", a);
return 0;
}
注:下列所有实验的输出当中,printf 函数中的占位符统一与变量a相匹配。
int a
-> printf("%d\n", a);
double a
-> printf("%.1f\n", a);
实验 | expression | output | remarks |
---|---|---|---|
A1.1 | int a = 11111*11111 | 123454321 | |
A1.2 | int a = 111111*1111111 | -539247567 | overflow in expression |
A1.3 | int a = 111111111*111111111 | 1653732529 | overflow in expression |
A2.1 | double a = 11111*11111 | 123454321.0 | |
A2.2 | double a = 111111*111111 | -539247567.0 | overflow in expression |
A2.3 | double a = 111111111*111111111 | 1653732529.0 | overflow in expression |
A3.1 | double a = sqrt(-11) | nan | 系统没有报错 |
A3.2 | int a = sqrt(-11) | -2147483648 | 系统没有报错 |
A4.1 | double a = 1.0/0.0 | inf | |
A4.2 | double a = 0.0/0.0 | nan | |
A4.3 | int a = 1.0/0.0 | -272632320 | |
A4.4 | int a = 0.0/0.0 | -272632320 | |
A5.1 | int a = 1/0 | -272632320 | Division by zero is undefined |
A5.2 | double a = 1/0 | 0.0 | Division by zero is undefined |
从上列实验可以观察出:
int
和double
都不可以处理较大的数- 在做不正确的计算时,
double
时常会返回nan
(not a number) 或者inf
(infinity)
#include <stdio.h>
#include <math.h>
int main(int argc, const char * argv[]) {
int a, b;
scanf("%d%d", &a, &b);
printf("%d %d\n", a ,b);
return 0;
}
实验 | input | output | remarks |
---|---|---|---|
B1 | 12 2 | 12 2 | 空格分离 |
B2 | 12 2 | 12 2 | 12 2 不同行 |
B3 | 12 2 | 12 2 | 12 和 2 前面后面有大量空格、tab、甚至空行 |
B4.1 | 12 s | 12 0 | 空格分离 |
B4.2 | 12 s | 12 0 | 12 2 不同行 |
B4.3 | 12 s | 12 0 | 12 和 2 前面后面有大量空格、tab、甚至空行 |
1.5.3 习题
本章习题过于简单,不再赘述。