前言
\(2021\) 年 \(9\) 月 \(1\) 日起,全新的 NOI Linux 2
正式替代了舊版 NOI Linux
,成為 NOI 系列賽的官方比賽環境。
免責聲明
-
本文信息來源於 NOI 官網公布的正在實施的技術規范,一些選手的實踐經驗,向 NOI 技術委員會詢問得到的回復等,並進行了一定整理和加工,以供各位參賽選手參考。
-
本文不應被視為對 NOI 官網公布的技術規范的官方解讀,官方規范的最終解釋權歸屬 NOI 科學委員會,作者不保證本文的內容完全准確。對於規范中未作出明確規定,不確定性較大的內容,將會用 斜體 進行標注。
-
因為 NOI 系列賽基本采用無實時反饋的賽制,選手無法通過向 OJ 提交,獲得提交反饋的方法測試其代碼在官方評測環境下是否正常編譯,運行結果是否符合期望。選手應理解這一賽制產生的不確定性,並自行承擔相關風險。作者不為任何因這一不確定性造成的成績波動承擔責任。
系統配置情況
NOI Linux 2.0
是基於 Ubuntu 20.04 LTS
改造而成的系統,為 \(64\) 位系統。
系統內自帶 g++
編譯器,版本 \(9.3.0\)(編譯時如果未指明語言標准,默認采用 C++14 標准),另外有 Python \(2.7\) 和 \(3.8\),雖然 Python 並非競賽語言,但可以使用 Python 編寫一些輔助性程序(如數據生成器,對拍器等)。
IDE 有 Code::Blocks,Geany。
編輯器有 VS Code(安裝了 C++ 擴展,但組件不完整,另外無簡體中文翻譯包),Vim,Emacs,gedit,Sublime Text \(3\) 等。
NOI 技術規范摘抄
將現有的技術規范簡單整理后做了份簡明,方便理解的版本。
請仔細閱讀並理解這部分內容后,再閱讀下面的部分。不清楚這部分的內容導致的盲目提問可能會給您帶來不必要的尷尬。
-
對於一道題目,選手只應該提交一個擴展名為
.cpp
的源文件,且其大小不應超過 \(100 \operatorname{KB}\),不應使用自己編寫的頭文件。(\(2022\) 年起全部 NOI 系列賽均只能使用 C++ 語言) -
選手程序應正常結束,
main
函數的返回值為 \(0\)。 -
選手程序不應執行如下違規操作:
-
試圖訪問網絡;
-
使用
fork
、exec
、system
或其它線程/進程生成函數; -
打開或創建題目規定的輸入/輸出文件之外的其它文件和目錄;
-
運行其它程序;
-
改變文件系統的訪問權限;
-
讀寫文件系統的管理信息;
-
使用除讀寫規定的輸入/輸出文件之外的其它系統調用;
-
捕獲和處理鼠標和鍵盤的輸入消息;
-
讀寫計算機的輸入/輸出端口;
-
禁止使用內嵌匯編;
-
禁止更改評測時使用的編譯選項。
-
-
在不違反上述規定的前提下,選手可以自由使用以下划線開頭的宏和函數。
我能使用...嗎?
-
bits/stdc++.h
:可以使用。需要注意這樣會將所有頭文件引入,會增大標識符沖突的風險。 -
__int128
:現在的系統是 \(64\) 位系統,因此可以使用。需要注意的是__int128
並不能直接使用cin/cout
,scanf/printf
進行輸入輸出,需要手寫輸入輸出函數(類似於快讀快輸)。 -
__gcd()
,__builtin_clz()
等一部分下划線開頭函數:可以使用(因為沒有被禁止的操作)。 -
gets()
:因為存在緩沖區溢出的問題,已經於 C++11 中被棄用,C++14 中被廢除。可以使用fgets()
替代。 -
itoa()
:不是標准庫中的函數。是否能使用取決於本機能否正常編譯。 -
在代碼中手動開啟
-O2
等優化選項:不可以。評測時只能按照 PDF 首頁給出的編譯選項編譯程序,擅自更改編譯選項屬於違例。 -
指令集:不可以。理由同上。
-
pb_ds
:可以使用。 -
無序關聯式容器:C++11 起可以直接使用,C++98/03 時它們在
std::tr1
命名空間下(是否能在比賽中使用std::tr1
命名空間尚不清楚)。需要注意它們的最壞復雜度是線性的。 -
基於范圍的
for
循環:C++11 起可以使用。 -
auto
類型說明符:C++11 起可以使用。 -
tuple
:C++11 起可以使用。 -
多線程:不能使用。
-
register
:C++11 起被棄用,C++17 起被移除。因此 C++11 后使用它不會造成任何優化效果。 -
列表初始化:C++11 起可以使用。需要注意的是 Windows 下部分編譯器在使用 C++11 以前標准編譯使用列表初始化的程序時,只給出警告而無錯誤。更推薦的做法是使用構造函數。
-
隨機函數:沒有限制。但
random_shuffle
已經於 C++14 起被棄用,C++17 起被移除。C++11 以后可以使用shuffle
函數替代。另外有關隨機化造成的評測結果波動引發的申訴,按規定將不被接受。
比賽系統的使用
考慮到有不少選手不熟悉 Linux 系統,還有不少地方仍然使用 Windows 作為比賽環境,因此特開辟一個板塊,講解 Linux 與 Windows 的相關使用技巧。
有關 Linux 和 Windows 下命令行使用的相關技巧,OI Wiki 講述得非常詳細,這里主要是介紹命令行使用以外的一些注意事項。
更改棧空間
一般來說,評測時的棧空間限制等於內存限制。但系統默認的棧空間往往較小,有時會出現官方評測時正常運行,而本地測試時爆棧的情況。這時候就需要對棧空間進行更改。
在 Linux 系統下,由 ulimit
對程序使用的資源進行限制。
輸入 ulimit -s <num>
可以將棧空間更改為 \(\text{num}\) KiB(如 ulimit -s 262144
可以將棧空間改為 \(256\) MiB),ulimit -s unlimited
可以將棧空間改為無限制。ulimit -a
可以查看各項資源的限制情況。
需要注意的是,ulimit
對包括棧空間在內的資源限制的配置僅在 當前終端 下有效。
對於 Windows 系統,棧空間在程序編譯時確定,准確來說,由連接器來處理棧空間的大小問題。在編譯時傳入如下參數 -Wl,--stack=
num Byte
(如
-Wl,--stack=268435456
將棧空間確定為
\(256\) MiB)。
查看樣例文件
一般情況下,考場下發的樣例文件是 Linux 格式的(換行為 \n
),而 Windows 下的換行為 \r\n
,因此如果用記事本打開的話,因為無法正確識別換行的原因,樣例會無法正常顯示(可能表現為無換行,換行符被黑矩形代替等)。
使用 VS Code 等高級編輯器可以有效解決這一問題(還能實現換行格式的轉換)。當然如果沒有提供 VS Code 的話,也可以用系統自帶的寫字板。
當然這只是解決了顯示問題,如果你嘗試在寫字板打開文件后,將輸入直接復制到命令行,你可能會發現還是不能正常讀入。正確的方法是在代碼中添加重定向/文件流,或者在命令行中使用管道。
參考資料
- NOI 系列賽常見技術問題整理 - Studying Father's luogu blog
- [洛谷日報#86]OIer 必知的編程技巧(2018 年的文章,部分內容可能已經過時)
- 命令行 - OI Wiki
本文搬運自別人持續更新的文章留作自用,如有更新請提醒一下。