杭電OJ測試資料探勘計畫

2021-06-29 10:22:08 字數 1595 閱讀 2766

前言

首先,hduoj已經出現多年,上面的大部分經典題目已經被被人咀嚼透爛了,也能通過搜尋引擎搜尋到許多現成的**。如果有測試資料,那麼就能拿自己的程式的輸出與前人的程式的輸出進行比對,找出問題所在。

然後,對於沒有被別人嚼爛的題目,也可以借助測試資料,更好地分析程式問題所在,不至於僅僅過了簡單的sample而過不了測試資料。

最後,對於想刷單題排行榜的人,可以嘗試衝擊0ms、0kb的極限。

一直很疑惑,哪些0ms,0kb的評判結果是怎麼出來的。

測試資料的獲取方法

在faq頁面,可以看到候選答案提交之後online judge的多種反饋結果。

只需選擇其中3種我們有把握一定能產生的錯誤,那麼就可以通過二分法,將測試資料的長度以及測試資料的每個位元組都找出來。

獲取測試資料的長度

設定猜測長度guess,結合讀取到的實際長度,比較兩者,分別人為地產生3種錯誤即可折半地逼近正確的實際長度。

其**如下

#include #define maxlen 0x7fffffff

#define minlen 0

char buffer[0x10000];//64kb

int guess = 0;

// re

void equal(void)

// ole

void less(void)

}// tle

void greater(void)

}int main(void)

if (count < guess)

else if (count == guess)

else

return 0;

}

顯然,最多隻需猜測log2(maxlen)次即可,就算他是32位整數,也就是31次猜測,必然得出測試資料的長度來。

獲取測試資料的每個位元組

同樣是利用二分法來猜測每個位元組的值。每個位元組只需最多8次猜測即可得出結果。其**如下:

#include int guess = 0;

int skip = 0;

// re

void equal(void)

// ole

void less(void)

}// tle

void greater(void)

}int main(void)

if (count == skip)

else if (ch < guess)

else

}count++;

} return 0;

}

優化

對於某些題目,如果我們預先知道了輸入資料僅僅是ascii文字,那麼很顯然可以將猜測範圍縮小至0~127的範圍。

對於另一些題目,比如輸入是整數,整數之間以空白符(空格、回車、tab)分割,那麼顯然猜測範圍可以進一步縮小為'0'~'9'以及'\n','\t', ' ',一共13種。如此一來最多隻需猜測4次即可得出每個位元組的值。

杭電oj 2102 A計畫

problem description 可憐的公主在一次次被魔王擄走一次次被騎士們救回來之後,而今,不幸的她再一次面臨生命的考驗。魔王已經發出訊息說將在t時刻吃掉公主,因為他聽信謠言說吃公主的肉也能長生不老。年邁的國王正是心急如焚,告招天下勇士來拯救公主。不過公主早已習以為常,她深信智勇的騎士lj肯...

杭電OJ 2016 資料的交換輸出

problem description 輸入n n 100 個數,找出其中最小的數,將它與最前面的數交換後輸出這些數。input 輸入資料有多組,每組佔一行,每行的開始是乙個整數n,表示這個測試例項的數值的個數,跟著就是n個整數。n 0表示輸入的結束,不做處理。output 對於每組輸入資料,輸出交...

杭電OJ 2016 資料的交換輸出

problem description 輸入n n 100 個數,找出其中最小的數,將它與最前面的數交換後輸出這些數。input 輸入資料有多組,每組佔一行,每行的開始是乙個整數n,表示這個測試例項的數值的個數,跟著就是n個整數。n 0表示輸入的結束,不做處理。output 對於每組輸入資料,輸出交...