使用手冊
目錄
常見問題 FAQ
請先查看FAQ
網站操作
搜尋題目
在題目列表頁面中
你可以在右方看到搜尋篩選器 (problem search)
- 輸入文字以搜尋題目標題或代號
- 勾選全文搜尋以包含題目內文
- 篩選分類已快速找到你想要的題目,包含預設、基礎、競賽、AP325
或是使用標籤尋找分類
題目介面
左邊顯示題目的敘述
右邊欄位則顯示則有提交按鈕、提交動態、測資資訊以及作答語言
下滑可以看到評論區
可以在這裡討論題目 對評論按讚
或是提交錯誤回報Report an issue
如果你想留言分享你的解法或是解題思路,請避免直接貼上完整程式碼 提供程式碼時,請善用成對的反引號(```)包覆你的程式碼 效果如下
text = input()
print("hello, ",text)
點擊submit a solution
可以提交答案
在作答介面下方 你可以選擇作答語言
作答完畢後 點擊提交!
然後你會看到結果頁面
關於輸出 請見狀態代碼-Status Codes
管理個人頁面
到右上方進入個人資料介面
點選Edit profile
開啟深色模式
首先打勾 Enable experimental features (啟用實驗性功能)
點擊update profile
後畫面會刷新
這時你可以看到出現了site theme
的選項
- Follow system defalt - 使用windows系統設定
- Light - 亮瞎眼的白色主題
- Dark - 正常人的黑色主題
更改預設作答語言
如圖選擇你最常用的語言
管理個人資料
使用Change your password
或Change your email
更改你帳密
右邊欄位可以加入/退出組織
更改大頭貼
- 點擊
Change your avatar
- 使用你註冊TFOJ的電子信箱登入該連結的網站
- 上傳你的圖片
- Done!
因為網站快取的緣故,你可能需要重啟網站來應用變更。
關於裁判機
評分主機資訊:
注意! 管理員保留隨時 rejudge 的權利
本系統目前所有支援的程式語言請見runtimes
預設開啟brainfuck python c c++ assembly
如需開啟其他語言 請直接留言或聯絡我們
狀態代碼(Status Codes)
這個頁面列出了 TFOJ 系統中可能遇到的所有狀態代碼及其描述。需要注意的是,一個測試案例可能會有多個狀態代碼(特別是在非 AC 判定的情況下),
此時系統會顯示優先級最高的狀態代碼。本頁的狀態代碼按照優先級由低到高的順序排列。
AC - Accepted(通過)
你的程式通過了所有測試!有時候,系統可能會提供額外的反饋訊息。
WA - Wrong Answer(答案錯誤)
你的程式雖然沒有在執行期間崩潰,但輸出結果不正確。和 AC 類似,系統可能會提供反饋訊息,指出你錯在哪裡。
IR - Invalid Return(無效返回)
你的程式 return 了非零錯誤碼(如果你不是使用 C++ 這類原生語言,那就是程式崩潰)。對於 Python 或 Java 等語言,通常會顯示拋出的 Exception,例如 NameError
或 java.lang.NullPointerException
。
RTE - Runtime Error(執行時錯誤)
你的程式在執行期間發生錯誤。這通常發生在 C 或 C++ 這類原生語言中。TFOJ 系統會將一些常見的 RTE 錯誤映射為更有用的描述,如下所示:
反饋 | 描述 |
---|---|
segmentation fault, bus error | 程式因為 SIGSEGV 或 SIGBUS 信號被終止。通常代表記憶體不足,但也可能是因為陣列越界存取。 |
floating point exception | 程式執行了錯誤的算術操作,例如除以零。 |
killed | 程式因為某種原因被終止(原因不明)。 |
{} syscall disallowed | 如果你看到此訊息,代表程式嘗試使用不允許的系統呼叫。如非必要,應不會看到此錯誤。如有疑問,請提交 issue以協助DMOJ官方排查。 |
std::bad_alloc | 無法分配足夠的記憶體。 |
failed initializing | 程式在初始化時使用了過多的全域變數。例如,在 64MB 記憶體限制下,宣告 int arr[10000][10000] 將佔用 381MB,超過了限制。 |
OLE - Output Limit Exceeded(輸出超限)
你的程式輸出了過多的資料到 stdout
,通常超過 256MB(視題目而變)。
MLE - Memory Limit Exceeded(記憶體超限)
你的程式使用了過多的記憶體。有時會以 RTE 類似的形式顯示,例如 segmentation fault 或 std::bad_alloc。
TLE - Time Limit Exceeded(時間超限)
你的程式超時。
IE - Internal Error(內部錯誤)
若出現此錯誤,表示系統評測器發生了錯誤,或題目設定有問題,請通知管理員。
解題範例
,+[->++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.---.+++++++..+++.-------------------------------------------------------------------.------------.--------------------------------<.,----------[++++++++++.,----------]++++++++++.,+]
C: gcc -std=c99 (gcc 13)
C解題範例:
#include<stdio.h>
int main() {
char s[9999];
while( scanf("%s", s) != EOF ) {
printf("hello, %s\n", s);
}
return 0;
}
CPP: g++ -std=c++17 (g++17 13)
CPP解題範例:
#include <iostream>
using namespace std;
int main() {
string s;
while(cin >> s) {
cout << "hello, " << s << endl;
}
return 0;
}
import java.util.Scanner;
public class JAVA {
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
String s;
while (cin.hasNext()) {
s = cin.nextLine();
System.out.println("hello, " + s);
}
}
}
PYTHON: Python 3.12.4
PYTHON解題範例:
while True:
try:
s = input()
print('hello, ' + s)
except:
break
技巧
給 Java 參賽者的提示
讀取輸入
Java 中的 java.util.Scanner
在處理 System.in
時非常慢,因為它需要進行大量高成本的轉換。如果您在使用 Scanner
類時遇到超時的問題,請考慮改用 java.io.BufferedReader
來讀取輸入。
Scanner in = new Scanner(System.in);
int a = in.nextInt();
int b = in.nextInt();
變為
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
每當您需要讀取輸入時,應該嘗試使用 BufferedReader
。它比 Scanner
快 100 倍以上!
注意:底層的輸入流不是檔案流,因此即使未到達輸入的結尾,像 BufferedReader.ready
這樣的輪詢方法也可能會錯誤地返回 false
。
排序陣列
Java 7 使用雙樞軸快速排序算法來排序基本型別的陣列。雖然在大多數情況下這提供了快速排序,但它在最壞情況下的時間複雜度是 \(O(n^2)\)——對於大型陣列來說非常糟糕。如果您的程式在使用 Arrays.sort(primitive[])
時超時,請考慮使用 Collections.sort
或 Arrays.sort(Object[])
。後者使用 Timsort 實作,保證最壞情況下的性能為 \(O(n \log n)\) :比快速排序的 \(O(n^2)\) 快得多。在大多數情況下,將使用基本型別排序的程式轉換為物件排序是很簡單的:
int[] a = new int[N];
for(int i = 0; i < N; i++) {
a[i] = ...
}
Arrays.sort(a);
變為
Integer[] a = new Integer[N];
for(int i = 0; i < N; i++) {
a[i] = ...
}
Arrays.sort(a);
這兩種變化的唯一差別是將 int
資料型別改為 Integer
資料型別。在大多數方面,它們是等價的,除了 Integer
是物件(因此使用 Array.sort(Object[])
方法重載,而不是可能慢得多的 Arrays.sort(int[])
)。
但是請注意,在物件陣列上排序通常比在基本型別陣列上排序要慢得多。當您確定基本型別陣列的排序可以滿足需求時(通常是這樣),不要使用物件陣列的排序。
hsa.Console
有些 ICS 課程使用 hsa.Console
物件來進行控制台操作。TFOJ 不支援 hsa.Console
類。TFOJ 主要是一個基於文字的輸入/輸出系統,因此需要使用標準的 IO 方法。
基本上,您應該使用 System.out.print
代替 hsa.Console.print
,並使用 BufferedReader
或 Scanner
(不建議:見上文)類代替 hsa.Console.readChar
。
給 Python 參賽者的提示
執行速度
Python 作為一種直譯語言,明顯比 C、C++ 或 Java 等編譯語言慢。速度差異非常顯著,Python 可能比上述語言慢 20 到 40 倍。
在現實世界中,這比在算法競賽和線上判題系統上問題要小。這個問題可以通過使用 PyPy 直譯器(而不是 CPython 直譯器)來緩解,因此如果您確信您的解答是正確的,但超時了,請嘗試使用 PyPy 重新提交。本判題上的許多問題都設計為在 Python 中具有良好執行時間的解答可以被接受,但您應該注意,對於某些問題,Python 是不可能被接受的。原因是,如果設定的時間限制讓正確的 Python 解答可以通過,那麼用更快語言(如 C、C++ 或 Java)撰寫的錯誤解答也會通過。
不幸的是,我們無法讓您的 Python 提交在判題系統上運行得和 C 一樣快,因此您能做的最好選擇就是學習上述語言之一(如果您還沒有學的話),以便在 Python 不夠快時使用。
讀取輸入
通常,您的程式瓶頸不在於算法速度,而在於從輸入讀取和向輸出寫入資料的速度。您可以通過直接從 sys.stdin
讀取來加快輸入。
import sys
for line in sys.stdin:
# 執行一些操作
sys.stdin
是一個類似檔案的物件。也就是說,您可以像操作 open
返回的檔案一樣操作它。
加快輸入的一個快速技巧是簡單地使用 sys.stdin.readline
來取代所有字串輸入呼叫。
對於 Python 2,這意味著
import sys
raw_input = sys.stdin.readline
對於 Python 3,這意味著
import sys
input = sys.stdin.readline
一個更快更好的解決方案是將所有問題輸入進行緩衝(如果您知道輸入的大小可管理),並自行解析:
import sys
all_data = sys.stdin.read().split('\n')
上述範例將所有輸入行儲存在列表 all_data
中。all_data[0]
包含第一行輸入,all_data[1]
包含第二行,依此類推。這是在 Python 中輸入資料的最快方式。
更快地讀取實數和整數值
本節僅適用於 Python 2 參賽者(Python 3 沒有此問題)。
如果在 IO 速度上遇到困難,一個簡單的技巧是將所有的 input
呼叫改為 sys.stdin.readline
呼叫,並自行進行型別轉換。如果您知道 N
將是一個整數,您可以拋棄 input
呼叫,自己進行型別轉換。
N = input()
變為
N = int(sys.stdin.readline())
自行進行型別轉換要快得多!這也可以保護您免受其他線上判題系統中可能存在的輸入中惡意的尾隨回車的影響。
基準資料(Python 2),從標準輸入讀取一百萬個整數:
input()
:3.064 秒int(raw_input())
:0.844 秒raw_input = sys.stdin.readline; int(raw_input())
:0.427 秒
基準資料(Python 3),從標準輸入讀取一百萬個整數:
int(input())
:0.879 秒input = sys.stdin.readline; int(input())
:0.294 秒
毫無疑問,應該使用 int(sys.stdin.readline())
來讀取整數,使用 float(sys.stdin.readline())
來讀取實數,等等。Python 3 參賽者也應該盡可能使用 sys.stdin
。
使用 site 函數(如 exit)
TFOJ 禁止訪問 site
模組,因此注入到內建命名空間的函數(如 exit
)是不允許的。
對於 exit
,請使用 sys.exit()
代替。
給 C/C++ 參賽者的提示
記憶體配置
避免將大型陣列宣告為區域變數,因為這通常會導致您耗盡堆疊空間並導致執行時錯誤。
不要這樣做:
int main()
{
int N;
scanf("%d", &N);
int arr[N];
for(int i = 0; i < N; i++) scanf("%d", &arr[i]);
}
請考慮:
int arr[100001];
int main()
{
int N;
scanf("%d", &N);
for(int i = 0; i < N; i++) scanf("%d", &arr[i]);
}
只要您知道 N
的最大範圍(幾乎所有問題都會給出上限),在全域範圍宣告大型陣列是一種更安全的方法。不過,請注意陣列索引越界的問題。
輸入和輸出
出於性能考慮,建議 C++ 使用者使用 C 風格的輸入和輸出,即使用 scanf
和 printf
,而不是 cin
和 cout
。
如果您必須使用 cin
和 cout
,可以在 main
函數的頂部添加以下兩行程式碼:
int main()
{
cin.sync_with_stdio(0);
cin.tie(0);
...
以加快 cin
流的速度。這將使 cin
與 scanf
和 cout
取消同步。請注意,在與 stdio
取消同步後,您不應該使用 scanf
。
此外,當不需要刷新時,您不應該使用 endl
,而應該使用 \n
來輸出換行符。endl
的刷新行為可能會導致您的程式 TLE。
無符號整數輸入的快速方法
如果問題只需要讀取無符號整數型別,您可以在程式的頂部添加以下巨集:
#define scan(x) do{while((x=getchar())<'0'); for(x-='0'; '0'<=(c=getchar()); x=(x<<3)+(x<<1)+c-'0');}while(0)
char c;
您可以使用 scan(n)
來取代 std::cin >> n
或 scanf("%d", &n)
。
int、long 和 long long
在 judge 上,int
是 32 位元,long long
是 64 位元,而 long
可能是 32 位元或 64 位元,取決於裁判機的設定。
因此,建議使用 int
或 long long
,而不是 long
。