CSP复赛注意事项
1. 做题前准备
1.1 Windows 要显示扩展名
如果不显示扩展名创建的文本文件默认是 .txt
的,看起来是 apple.cpp
,但是实际是 apple.cpp.txt
, 会导致提交失败。
1.2 良好的代码规范
良好的代码规范,比如变量命名、函数命名、注释、空行分隔不同功能、合理封装函数等,这些虽然不会影响程序运行,但是能让你在调试的时候少走很多弯路。
1.3 打好草稿
做题的时候不要一上来就敲代码,可以在纸上写好思路或者用注释的形式在电脑上把自己的思路写出来,然后再去写代码一步步实现,尤其是模拟这种题目尤为重要,这样能避免思路混乱,做着做着不知道做啥了还可以回去看。
2. 程序编写注意事项
2.1 文件输入输出
- CSP 复赛要求用文件输入输出,一定要确保提交文件中使用
freopen()
进行文件读写。 - 开始做题时,可以先写上输入输出文件,然后注释掉,正常去做题,做题检查完毕后,取消注释。
#include <bits/stdc++.h>
using namespace std;
int main(){
freopen("题目要求的文件名字.in", "r", stdin);
freopen("题目要求的文件名字.out", "w", stdout);
....
return 0;
}
一定要注意!
- 代码文件名字是每道题的英文名字,每道题都有一个自己的
.cpp
源文件名。比如power.cpp
,live.cpp
,expr.cpp
,number.cpp
- 一定要进行文件操作!一定要核对文件名称,没有任何数字,只有英文!一定记得解除注释!
2.2 注意文件名
- 文件夹名:
apple
- 程序文件名:
apple.cpp
- 输入文件名:
apple.in
- 输出文件名:
apple.out
- 注意:诸如
apple1.in
,apple1.ans
这类带有数字的数据,是测试用的,最终提交的程序,文件操作不要有任何数字!!!
2.3 输出格式和大小写问题
注意题目要求每个输出结果在同一行,还是在不同行。或者输出yes
,NO
,right
,impossible
等英文提示时,是否要求首字母大写。
2.4 注意保存,不要关机
防止突发事件,至少 20 分钟手动保存一次。千万不要关机,否则程序会丢失。
2.5 头文件
虽然比赛可以使用万能头文件 <bits/stdc++.h>
,但是使用万能头文件时,创建变量和使用一些函数时需要格外注意,容易冲突。 如果能记住头文件,建议单独导入,常用头文件如下,一般可以直接写上去:
//STL专用,使用了哪种数据结构,就要用到哪种头文件
#include <map> // 键值对形式的关联容器
#include <vector> // 动态数组
#include <set> // 有序集合
#include <queue> // 队列
#include <stack> // 栈
#include <deque> // 双端队列
#include <string> // 字符串
#include <bitset> // 二进制位序列
#include <list> // 双向链表
// 哈希表实现的键值对形式的无序关联容器,当不需要有序性但需要快速查找时使用
#include <unorder_map>
// 哈希表实现的无序集合,用于需要快速查找而不需要有序的唯一集合
#include <unorder_set>
//C++必备头文件,cin、cout及其相关函数在这里
#include <isotream>
//strlen()、strcat()等字符串操作函数在这里
#include <cstring>
//sort()、lower_bound()、upper_bound()在这里
#include <algorithm>
//log()、sin()、pow()等数学运算的函数在这里
#include <cmath>
2.6 变量命名冲突
用了 using namespace std;
之后容易产生的问题是,有些自己的变量名比如time
、next
和标准命名空间中的变量名冲突,而且在 Windows 下编译器不报错,但是在 Linux 下会报错。 所以如果需要这几个单词:
- 可以使用首字母大写
Time
,Next
- 或者做一下变形,比如
tim
,nxt
- 或者定义成局部变量。
另外time
、next
等作为结构体的成员名是没问题的。 全局变量不要使用 y0
、 y1
、 yn
、 j0
、 j1
、 jn
,因为这些变量名称在 C++11 标准库里被定义了,不能再用作全局变量,否则编译会有警告或出错,但是这些变量可以用作局部变量。
2.7 变量初始化
变量的初始化常见有两种方式:输入和赋值。在使用变量之前记得要初始化。 如果定义成全局变量,则系统会自动初始化。
2.8 数组建议用全局数组
全局数组存放在数据区,而局部数组是在栈区的,全局数组可用的内存空间比局部数组可用的内存空间大很多很多。
2.9 注意时间和空间限制
1 秒内最大循环次数不要超过1 亿次。1 亿次有可能超时也有可能不超时。但是一两千万次通常不会超时,最好控制在 1e8
这个范围内。 通常题目会限制内存不能超过 256MB 或 512MB。所以要学会估计内存。
比如全局数组 int a[1000000]
占内存 1000000 * 4 / (1024 * 1024)MB ≈ 4MB
。 全局数组的大小通常最好不要超过1 千万。
CSP-J2023 第二轮的第一题,最大的测试数据是 10 亿,有人把数组开到了 10 亿从而爆 0, 这是 2023 年入门组爆 0 人数偏多的重要原因之一。 估算一下 10 亿数组所占的内存空间,假如数组类型是布尔类型,即 bool a[1000000000]
,则占内存 10,0000,0000*1/(1024*1024) ≈ 1000MB ≈ 1G
,这已超过题目的要求 512MB 一倍。 如果是定义成 32 位整型,即 int a[1000000000]
,则占内存约 4G
。
2.10 不开 long long 见祖宗
内存够用的情况下,开 long long
是非常有必要的:
- 防止溢出;
- 防止精度丢失。
- 测评的机器是 64 位 CPU,一次就可以读取一个
long long
类型的数据,而读取int
类型之后还要再进行切割,所以long long
类型的数据读取速度比int
更快(32 位 CPU 就反过来了)。