NOI 系列賽常見技術問題整理


前言

\(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\)

  • 選手程序不應執行如下違規操作:

    • 試圖訪問網絡;

    • 使用 forkexecsystem 或其它線程/進程生成函數;

    • 打開或創建題目規定的輸入/輸出文件之外的其它文件和目錄;

    • 運行其它程序;

    • 改變文件系統的訪問權限;

    • 讀寫文件系統的管理信息;

    • 使用除讀寫規定的輸入/輸出文件之外的其它系統調用;

    • 捕獲和處理鼠標和鍵盤的輸入消息;

    • 讀寫計算機的輸入/輸出端口;

    • 禁止使用內嵌匯編;

    • 禁止更改評測時使用的編譯選項。

  • 在不違反上述規定的前提下,選手可以自由使用以下划線開頭的宏和函數。

我能使用...嗎?

  • bits/stdc++.h:可以使用。需要注意這樣會將所有頭文件引入,會增大標識符沖突的風險。

  • __int128:現在的系統是 \(64\) 位系統,因此可以使用。需要注意的是 __int128 並不能直接使用 cin/coutscanf/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 的話,也可以用系統自帶的寫字板。

當然這只是解決了顯示問題,如果你嘗試在寫字板打開文件后,將輸入直接復制到命令行,你可能會發現還是不能正常讀入。正確的方法是在代碼中添加重定向/文件流,或者在命令行中使用管道。

參考資料

本文搬運自別人持續更新的文章留作自用,如有更新請提醒一下。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM