复赛注意事项

2024/10/19

# (一)文件输入输出

每年都会有一些选手,尤其是第一次参加第二轮(复赛)的选手,因为文件输入输出语句没写或没写对,遗憾爆0。

文件输入输出有多种方式,最简单的是freopen。假如题目的标题是apple,则只需要加入这两行:

freopen("apple.in", "r", stdin);
freopen("apple.out", "w", stdout);

注意,这里的函数名称和参数不能写错,任意一个地方出错都会导致程序爆0。比如,apple.in不能写成apple.txt,也不能写成apple.in.txt"r"不能写成"read",也不能写成'r'(这种情况编译器会报错)。

两行freopen中的三个参数是分别相反的:in文件对应着out文件,读取对应着写入,标准输入对应着标准输出。下面三种常见的错误写法,都会爆0。

第一种:

freopen("apple.in", "r", stdin);
freopen("apple.out", "r", stdout);

第二种:

freopen("apple.in", "r", stdout);
freopen("apple.out", "w", stdout);

第三种:

freopen("candy.in", "r", stdin);    
freopen("candy.in", "w", stdout);

另外,建议不要在程序的末尾写fclose函数。因为程序结束后,所占的内存就都释放了,fclose函数写不写是一样的。写的越多,意味着犯错的可能性越大。


# (二)程序提交格式

不同省份的提交格式可能不尽相同,常见的有两种。

第一种,在“工作文件夹”(不同的省份这个文件夹的位置不一样,也有可能指的是电脑桌面)中建立以选手准考号命名的文件夹,然后在准考证号文件夹内针对每一题再建立一个文件夹,再把源代码提交到对应的文件夹内。

假如某位选手的准考证号是TJ-00055,四道题的英文标题分别是applecashierdunemanhattan,则提交样式如下图所示:

- TJ-00055
    - apple
        - apple.cpp
    - cashier
        - cashier.cpp
    - dune
        - dune.cpp
    - manhattan
        - manhattan.cpp

如果你是用codeblocks建立的项目,那么每个项目源代码的名称都是main.cpp。可把main.cpp拷贝到准考证命名的文件夹内,然后把main.cpp重命名成相应的名称比如apple.cpp,或者保存存储时直接重命名。

若采用这种提交方式,不需要提交多余的文件,比如.in文件,.out文件,.exe文件。.in.out文件用来帮助选手测试,.exe是运行结果文件。如果把这些文件都提交了,也不会影响分数,因为评分时这些文件会被忽略掉。

第二种方式,以北京为例,是在浏览器中打开一个内网网址,然后把代码直接复制粘贴到网址里面,再点击底部的“提交”按钮即可。这种粘贴代码的网站叫做代码回收系统。

这种方式程序文件名称无所谓(比如codeblocks项目下的程序文件名叫main.cpp),只需要把代码直接复制粘贴到网址里即可,跟平时提交到洛谷等在线评测网站的过程是类似的。当然这种方式也不要忘了使用freopen进行文件输入输出。


# (三)Windows系统的扩展名要显示出来

有些Windows系统的电脑的扩展名是隐藏的,一定要让扩展名显示出来。否则轻则影响测试,重则爆0。比如有些机器隐藏了扩展名,选手将程序命名为apple.cpp,实际上是apple.cpp.cpp;选手将输入文件命名为apple.in,实际上是apple.in.txt


# (四)NOILinux建立项目的位置

如果你用的是NOILinux系统,那么不要把C++项目建立在桌面,因为“桌面”这两个字是汉字,会导致无法编译。建议把项目建立在英文路径下,比如/home/username/。之后在编译完成后,可以把.cpp文件放到桌面对应目录中,这样就可以方便地提交代码。


# (五)NOILinux建立.in文件

.in文件需要手动创建,.out文件则不需要手动创建,因为运行程序后会自动生成。

Windows系统中创建.in文件比较简单,右键点击空白处,选择新建文本文件即可。

NOILinux系统与Windows系统差别较大,在NOILinux系统中,右键点击空白处无法创建文本文件。可用下面三种方式来创建。

第一种,运行代码后,会生成xxx.out文件比如apple.out,然后把apple.out在同一目录下复制粘贴,会生成apple(复件).out,将apple(复件).out重命名为apple.in

第二种,点击桌面左下角的“九个点”按钮,在弹出的界面中的第一页选择“文本编辑器”,注意文件要保存到程序项目的路径下。

第三种,在终端里进入程序项目所在的路径,然后用touch apple.ingedit apple.in的指令来创建apple.in文件。

推荐新手使用最简单的第一种。


# (六)文件名都是小写

根据历年csp-js/noip相关的比赛来看,输入文件名、输出文件名、以及源代码的文件名称都是小写的。


# (七)输出格式

如果题目要求数据之间加空格,那就不能换行输出。比如要求输出:

1 2 3

如果选手输出:

1
2
3

则不能得分。

大小写也要注意,需要仔细看清题目是要求全大写、全小写还是首字母大写。比如要求输出Yes,则输出YESyesyES等均不能得分。


# (八)可多次提交代码

每做出一题,提交一题。每题写出一版代码,先提交上去,后面如果有更好的方法写完再次提交,会把先前提交的代码覆盖掉,以最后一次提交为准。

不要把所有的代码等到最后一次性提交,这样可以避免遇到突发情况来不及提交。

每写若干行代码,可保存一次。这样可以避免因为意外情况比如死机重启导致写好的代码丢失。


# (九)头文件

包含常用的头文件,比如iostreamcstdioalgorithm,或者直接包含万能头文件bits/stdc++.h


# (十)变量名冲突

用了using namespace std;之后容易产生的问题是,有些自己的变量名比如timenextstd命名空间中的变量名冲突,而且在Windows下编译器不报错,但是在Linux下报错。所以如果需要这几个单词,可以使用首字母大写TimeNext;或者做一下变形,比如timnxt;或者定义成局部变量。

另外timenext等作为结构体的成员名是没问题的。

全局变量不要使用y0y1ynj0j1jn。因为这些变量名称在C++11标准库里被定义了,不能再用作全局变量,否则编译会有警告或出错。但是这些变量可以用作局部变量。


# (十一)变量初始化

变量的初始化常见有两种方式:输入和赋值。在使用变量之前记得要初始化。如果定义成全局变量,则系统会自动初始化。


# (十二)数组建议用全局数组

全局数组可用的内存空间比局部数组可用的内存空间大很多很多。


# (十三)注意时间和空间限制

1秒内最大循环次数不要超过1亿次。1亿次有可能超时也有可能不超时。但是一两千万次通常不会超时。

通常题目会限制内存不能超过256兆或512兆。所以要学会估计内存。比如全局数组`int a

[1000000]`占内存:

100 0000 * 4 / (1024 * 1024) 兆 ≈ 4兆

全局数组的大小通常最好不要超过1千万。CSP-J2023第二轮的第一套题,最大的测试数据是10亿,有人把数组开到了10亿从而爆0,这是2023年入门组爆0人数偏多的重要原因之一。

这里我们估算一下10亿数组所占的内存空间,假如数组类型是布尔类型,即bool a[1000000000],则占内存:

10,0000,0000 * 1 / (1024 * 1024) ≈ 1000兆 ≈ 1G

这已超过题目的要求(512兆)一倍。如果是定义成32位整型,即int a[1000000000],则占内存约4G。


# (十四)注意数组越界

数组越界是最常见的错误之一。比如数组下标从0开始,但是选手写成了从1开始,或者数组下标写成了负数。这种错误在Windows下不会报错,但是在Linux下会报错。检查数组下标是否越界,可以在循环中加入打印语句,看看数组下标是否超出范围。


# (十五)注意死循环

死循环是指循环条件永远不会结束,比如while(1)for(;;)。这种死循环会导致程序超时。记住如果使用死循环,一定要在循环体内加入break语句。


# (十六)注意递归深度

递归深度不要超过1000层。如果递归深度过深,会导致程序爆栈。


# (十七)注意变量类型

变量类型要选择合适的类型,比如intlong longdouble。如果题目要求输出的是整数,那么就不要用double,而是用intlong long要检查试卷的监测点数据范围,比如如果数据范围是1 ≤ n ≤ 10^9,那么就不能用int,而是要用long long类型。如果是计算变量预计超出也需要使用long long类型。 关于long long类型,可以用%lld来输出,也可以用%I64d来输出。但是%I64dMicrosoft的编译器才支持的,%lldgcc编译器支持的。


# (十八)注意浮点数精度

浮点数精度问题是指浮点数的精度不够,导致输出结果不准确。比如1.0/3.0的结果是0.3333333333333333,但是如果只输出小数点后两位,那么就会输出0.33。这种情况下,可以用printf("%.2lf", 1.0/3.0)来输出结果。 如果是计算中给变量赋值,那么可以使用math.h中的函数,比如roundceilfloor等函数。 比如round(1.0/3.0)的结果是0ceil(1.0/3.0)的结果是1floor(1.0/3.0)的结果是0。 他们的功能分别对应的是

  • round:四舍五入
  • ceil:向上取整
  • floor:向下取整

# (十九)注意头文件引入

不要省略头文件,比如#include <iostream>#include <cstdio>#include <algorithm>等。省略头文件会导致编译错误。 可以使用万能头文件#include <bits/stdc++.h>,这个头文件包含了所有常用的头文件。


# (二十)注意代码风格

代码风格要统一,比如缩进、空格、换行等。可以使用codeblocksvscode等编辑器自带的格式化功能,或者使用clang-format等工具来格式化代码。


# (二十一)注意代码注释

有时我们调试时没有创建.in文件,那么我们可以先注释掉freopen函数,等到提交时再取消注释。千万注意不要忘记取消注释,否则会爆0。


# (二十二)noi 系统使用以及 codeblocks 使用

virtualbox (opens new window) 是一个虚拟机软件,可以在虚拟机中安装NOILinux系统,然后在NOILinux系统中使用codeblocks来编写代码。

NOILinux (opens new window) 是一个Linux系统,可以在virtualbox中安装,然后在NOILinux系统中使用codeblocks来编写代码。


上次更新: 2024-10-19 03:40:51