CSP-J 2024 初賽解析

StelaYuri發表於2024-09-22

時間緊任務重,可能有誤,煩請指正 QwQ


第1題 (2分)

32 位 int 型別的儲存範圍是?

A. -2147483647 ~ +2147483647

B. -2147483647 ~ +2147483648

C. -2147483648 ~ +2147483647

D. -2147483648 ~ +2147483648

32 位 int 型別,除最高位為符號位外,剩下 31 位均為數字。但 0 的二進位制最高位也是 0,所以除了 0 以外,正整數部分只有 \(2^{31} - 1 = 2147483647\) 個數,而負整數部分有 \(2^{31} = 2147483648\) 個數字。

第2題 (2分)

計算 \((14_8 − 1010_2) \times D_{16} − 1101_2\)的結果,並選擇答案的十進位制值:

A. 13

B. 14

C. 15

D. 16

\(14_8 = 12_{10}\)

\(1010_2 = 10_{10}\)

\(D_{16} = 13_{10}\)

\(1101_2 = 13_{10}\)

\((12 - 10) \times 13 - 13 = 13\)

第3題 (2分)

某公司有 10 名員工,分為 3 個部門:A 部門有 4 名員工,B 部門有 3 名員工、C 部門有 3 名員工。現需要從這 10 名員工中選出 4 名組成一個工作小組,且每個部門至少要有 1 人。問有多少種選擇方式?

A. 120

B. 126

C. 132

D. 238

分類討論,三個部門選四個人,且每個部門至少要有一人

① A部門選兩人,其他部門選一人,\(C_4^2\times C_3^1 \times C_3^1 = 54\)

② B部門選兩人,其他部門選一人,\(C_4^1\times C_3^2 \times C_3^1 = 36\)

① C部門選兩人,其他部門選一人,\(C_4^1\times C_3^1 \times C_3^2 = 36\)

\(54+36+36=126\)

第4題 (2分)

以下哪個序列對應數字 0 至 7 的 4 位二進位制格雷碼(Gray code)?

A. 0000,0001,0011,0010,0110,0111,0101,1000

B. 0000,0001,0011,0010,0110,0111,0100,0101

C. 0000,0001,0011,0010,0100,0101,0111,0110

D. 0000,0001,0011,0010,0110,0111,0101,0100

格雷碼的性質為:

  • 相鄰兩個編碼只能有一位不同
  • 首尾兩個編碼視作相鄰,也只能有一位不同
  • 同一編碼不能重複出現

明顯只有 D 選項符合條件

第5題 (2分)

記 1KB 為 1024 位元組(byte)、1MB 為 1024KB,那麼 1MB 是多少二進位制位(bit)?

A. 1000000

B. 1048576

C. 8000000

D. 8388608

\(1\text{ MB} = 1024\text{ KB} = 1024\times 1024 \text{ B} = 1024 \times 1024 \times 8 \text{ bit} = 8388608\text{ bit}\)

第6題 (2分)

以下哪個不是 C++中的基本資料型別?

A. int

B. float

C. struct

D. char

struct 結構體不算基本型別

第7題 (2分)

以下哪個不是 C++ 中的迴圈語句?

A. for

B. while

C. do-while

D. repeat-until

可以用排除法做

do-while 是先做一次迴圈內的程式碼,再根據條件迴圈執行的語句,也是 C++ 的語句

第8題 (2分)

在 C/C++ 中,(char)('a'+13) 與下面的哪一個值相等?

A. 'm'

B. 'n'

C. 'z'

D. '3'

ASCII 碼錶中,小寫英文字母是按照字母表順序連續出現的

'a' + 13 就是從 'a' 開始往後數 13 個字母,即 'n'

第9題 (2分)

假設有序表中有 1000 個元素,則用二分法查詢元素 X 最多需要比較( )次。

A. 25

B. 10

C. 7

D. 1

二分法查詢 時間複雜度是以 2 為底數的對數,即 \(\log_2 n\)

\(n = 1000\) 時,\(\log_2 1000 \approx 10\)

或者可以模擬二分的過程,每次二分後要麼直接找到對應數字,要麼剩餘數量變成原來的一半,觀察做多少次可以剩 \(1\) 個數字即可

第10題 (2分)

下面哪一個不是作業系統名字?

A. Notepad

B. Linux

C. Windows

D. macOS

Notepad 是記事本

第11題 (2分)

在無向圖中,所有頂點的度數之和等於( )。

A. 圖的邊數

B. 圖的邊數的兩倍

C. 圖的頂點數

D. 圖的頂點數的兩倍

無向圖中,每條邊連線兩個點

根據度數的定義,無向圖中點的度數就是有多少條邊連線著當前點

那麼每條邊對於總度數的貢獻就是 \(2\)

即無向圖的總度數一定等於邊數 \(\times 2\)

第12題 (2分)

已知二叉樹的前序遍歷為 [A, B, D, E, C, F, G],中序遍歷為 [D, B, E, A, F, C, G],請問該二叉樹的後序遍歷結果是( )?

A. [D, E, B, F, G, C, A]

B. [D, E, B, F, G, A, C]

C. [D, B, E, F, G, C, A]

D. [D, B, E, F, G, A, C]

畫圖可得,這是一棵 7 個結點的滿二叉樹

第13題 (2分)

給定一個空棧,支援入棧和出棧操作。若入棧操作的元素依次是 1 2 3 4 5 6,其中 1 最先入棧,6 最後入棧,下面哪種出棧順序是不可能的?

A. 6 5 4 3 2 1

B. 1 6 5 4 3 2

C. 2 4 6 5 3 1

D. 1 3 5 2 4 6

模擬即可,明顯 D 選項在 1 3 5 出棧後,棧頂元素不論如何都不可能是 2

第14題 (2分)

有 5 個男生和 3 個女生站成一排,規定 3 個女生必須相鄰,問有多少種不同的排列方式?

A. 4320 種

B. 5040 種

C. 3600 種

D. 2880 種

三個女生必須相鄰,不妨假設三個女生為一個整體,與其餘五個男生之間的站位方案數為 \(A_6^6 = 6! = 720\)

三個女生內部也存在 \(A_3^3 = 3! = 6\) 種站位

因此總方案數為 \(720 \times 6 = 4320\)

第15題 (2分)

編譯器的主要作用是什麼?

A. 直接執行原始碼

B. 將原始碼轉換為機器程式碼

C. 進行程式碼除錯

D. 管理程式執行時的記憶體

A 原始碼沒法直接執行

C 除錯功能是編輯器提供的

D 管理計算機執行過程中的資源是作業系統乾的活

第 16 題 (10.5 分)

img

img

觀察程式可知

isPrime(n) 函式在判斷整數 n 是否是一個素數

countPrimes(n) 函式在求 \(2 \sim n\) 之間的素數數量

sumPrimes(n) 函式在求 \(2 \sim n\) 之間的素數總和

程式輸入一個整數 \(x\),輸出兩個整數:\(2\sim x\) 的素數數量以及 \(2 \sim x\) 的素數和

第16 - 1題(1.5 分)

當輸入為 "10" 時,程式的第一個輸出為 "4",第二個輸出為 "17"。

A. 對

B. 錯

\(10\) 以內的素數有 \(2, 3, 5, 7\)

數量為 \(4\),總和為 \(17\)

第16 - 2題(1.5 分)

若將 isPrime(i) 函式中的條件改為 i <= n / 2,輸入"20" 時,countPrimes(20) 的輸出將變為 "6"。

A. 對

B. 錯

首先觀察程式碼第 6 到 9 行,發現小於 \(2\) 的情況都已經被排除了,接下來迴圈過程一定滿足 \(n \ge 2\)

原本的程式碼是 i * i <= n,就是說 \(i\) 不會超過 \(\lfloor \sqrt n \rfloor\)

而改後的程式碼 i <= n / 2 表示 \(i\) 不超過 \(\lfloor \dfrac n 2\rfloor\)

發現在 \(n \ge 2\) 時,\(\lfloor \sqrt n \rfloor \le \lfloor \dfrac n 2\rfloor\) 一定成立

所以改後無非就是時間複雜度從 \(O(\sqrt n)\) 變成了 \(O(n)\),對答案無影響

輸入 \(20\) 時,\(20\) 以內的素數有 \(2,3,5,7,11,13,17,19\),共 \(8\)

第16 - 3題(1.5 分)

sumPrimes 函式計算的是從 2 到 n 之間的所有素數之和。

A. 對

B. 錯

易得

第16 - 4題(3 分)

當輸入為 "50" 時,sumPrimes(50) 的輸出為( )。

A.1060

B.328

C.381

D.275

\(50\) 以內的素數為 \(2,3,5,7,11,13,17,19,23,29,31,37,41,43,47\)

總和為 \(328\)

第16 - 5題(3 分)

如果將 for (int i = 2; i * i <= n; i++) 改為 for (int i = 2; i <= n; i++),輸入 "10" 時,程式的輸出( )。

A.將不能正確計算 10 以內素數個數及其和

B.仍然輸出 "4" 和 "17"

C.輸出 "3" 和 "10"

D.輸出結果不變,但執行時間更短

改後 if(n % i == 0) 這一句判斷一定會在 i == n 時成立

因此 return false 一定會執行

此時無法判斷素數

第 17 題 (15 分)

img

雖然是一道線性動態規劃,但很明顯簡單遞推一下也能做題

如果想要充分理解程式碼的意思,可以給這道題定一個題目背景:

小明現在想要上樓梯,共有 \(n+1\) 級臺階,其中第 \(1\)\(n\) 級的每一級臺階上都有一個整數,第 \(i\) 級臺階上的整數是 cost[i - 1]

小明現在正站在第 \(0\) 級臺階上,每一步他可以向上走 \(1\) 級或者跨 \(2\) 級,並且每一步走完之後,他都要把當前位置臺階上的數字加到答案裡去,直到他走到第 \(n+1\) 級臺階上為止

問答案的最小值

加個背景的話可能題目就好理解多了,現在來簡單分析下程式碼

首先輸入的 cost 陣列下標是從 0 開始的,而動態規劃過程中的 dp 陣列下標是從 1 開始的,不要搞混

小明一開始就站在第 \(0\) 級臺階上,所以 初始狀態為 dp[0] = 0,但程式碼中沒寫出來,也沒關係

如果想走到第 \(1\) 級臺階上,那麼就只能從第 \(0\) 級臺階走上來,所以dp[1] = dp[0] + cost[1 - 1],也就是 dp[1] = cost[0]

從第 \(2\) 級臺階開始,第 \(i\) 級臺階的上一步只有第 \(i-1\) 級和第 \(i-2\) 級兩種情況,兩種情況取個最小值轉移過來即可,所以這一部分的狀態轉移方程為 dp[i] = min(dp[i-1], dp[i-2]) + cost[i-1]

最後目標是走到第 \(n+1\) 級臺階上,但由於第 \(n+1\) 級臺階沒有數字,所以不能用 cost 陣列,又由於 dp[n+1] = min(dp[n], dp[n-1]),所以直接 return 作為答案了

第17 - 1題(1.5 分)

當輸入的 cost 陣列為 {10, 15, 20} 時,程式的輸出為 15。

A.對

B.錯

模擬即可

第17 - 2題(1.5 分)

如果將 dp[i - 1] 改為 dp[i - 3],程式可能會產生編譯錯誤。

A.對

B.錯

陣列越界出現的是執行時錯誤,不是編譯錯誤

第17 - 3題(2 分)

程式總是輸出 cost 陣列中最小的元素。

A.對

B.錯

明顯不是取最小值輸出

第17 - 4題(3 分)

當輸入的 cost 陣列為 {1, 100, 1, 1, 1, 100, 1, 1, 100, 1} 時,程式的輸出為( )。

A.6

B.7

C.8

D.9

模擬即可,加到答案裡的數字對應的下標可以是 \((1, 3, 5, 7, 8, 10)\)

第17 - 5題(4 分)

如果輸入的 cost 陣列為 {10, 15, 30, 5, 5, 10, 20},程式的輸出為( )。

A.25

B.30

C.35

D.40

模擬即可,加到答案裡的數字對應的下標可以是 \((2, 4, 6)\)

第17 - 6題(3 分)

若將程式碼中的 min(dp[i - 1], dp[i - 2]) + cost[i - 1] 修改為 dp[i - 1] + cost[i - 2],輸入 cost 陣列為 {5, 10, 15} 時,程式的輸出為( )。

A.10

B.15

C.20

D.25

相當於完全變成了一個遞推

  • dp[0] = 0
  • dp[1] = cost[0] = 5
  • dp[2] = dp[1] + cost[0] = 5 + 5 = 10
  • dp[3] = dp[2] + cost[1] = 10 + 10 = 20

最後的答案是 min(dp[2], dp[3]) = 10

第18 題 (14.5 分)

img

分析 customFunction 這個函式,發現每次只有引數 b 會變成 b-1,並且過程中每次遞迴會把下一層答案 +a 後返回給上一層

觀察到 b == 0 時遇到邊界結束,所以總共遞迴 b 層,過程中共有 ba 相加

但在 b == 0 時執行了 return a,所以最終答案裡是有 b+1a 相加

綜上,customFunction(a, b) 的功能就是計算 \(a \times (b + 1)\)

最後輸出的是 pow(result, 2),也就是說程式輸入了兩個整數 \(x, y\),然後輸出 \((x \times (y + 1)) ^ 2\)

第18 - 1題(1.5 分)

當輸入為 "2 3" 時,customFunction(2, 3) 的返回值為 "64"。

A.對

B.錯

注意問的是函式返回值,而不是輸出是什麼!

返回值是 \(2 \times 4 = 8\)

第18 - 2題(1.5 分)

當 b 為負數時,customFunction (a, b) 會陷入無限遞迴。

A.對

B.錯

邊界條件是 b == 0,遞迴過程中 b 每次會減少,因此在 b 為負數時會無限遞迴下去

但有的同學可能會認為,int 型別減到負整數最小值之後,再 \(-1\) 會變成正整數最大值,最終執行 \(2^{32}\) 層遞迴之後確實還是會出現 b == 0 的情況。但這裡要注意,遞迴函式執行呼叫的是棧空間,棧空間能夠支援的遞迴層數遠小於 \(2^{32}\) 這一級別的數字。(即使支援,這也肯定會超出題目的空間限制)(即使題目空間限制給得很寬,目前家用電腦的記憶體容量也不支援)

第18 - 3題(1.5 分)

當 b 的值越大,程式的執行時間越長。

A.對

B.錯

如果 b 是正整數,遞迴的時間複雜度是 \(O(b)\),執行時間確實會隨著 b 的變大而變長

但上一題又問了負數的情況,所以有些小歧義,但負數時到後面會出現執行時錯誤,不算正常執行完程式,應該也可以不考慮

第18 - 4題(3 分)

當輸入為 "5 4" 時,customFunction(5, 4) 的返回值為( )。

A.5

B.25

C.250

D.625

問的是返回值

\(5 \times (4 + 1) = 25\)

第18 - 5題(3 分)

如果輸入 x = 3 和 y = 3,則程式的最終輸出為( )。

A."27"

B. "81"

C."144"

D."256"

\(\text{result} = 3 \times (3 + 1) = 12\)

\(12 ^ 2 = 144\)

第18 - 6題(4 分)

若將 customFunction 函式改為 "return a + customFunction(a-1, b-1)" 並輸入 "3 3",則程式的最終輸出為

A.9

B.16

C.25

D.36

模擬一遍

customFunction(3, 3)

= 3 + customFunction(2, 2)

= 3 + 2 + customFunction(1, 1)

= 3 + 2 + 1 + customFunction(0, 0)

= 3 + 2 + 1 + 0

= 6

\(6^2 = 36\)

第19 題 (15 分)

(判斷平方數)

問題:給定一個正整數 n,希望判斷這個數是否為完全平方數,即存在一個正整數 x 使得 x 的平方為 n。

試補全程式。

(實際上從原理上講,這題函式里也可以直接 return bound * bound == num;,沒必要用到迴圈,但題目就這樣考了,那就 for 一遍找答案吧)

根據題目意思,如果我們找到一個正整數 \(x\),滿足 \(x^2 = n\),那麼 \(n\) 就是一個完全平方數

所以這裡採用迴圈來找這個正整數 \(x\)

發現 \(x^2 = n\) 可以看作 \(x = \sqrt n\),所以要找的數字一定不會超過 \(\sqrt n\)

所以只需要把 \(1 \sim \sqrt n\) 內的每一個整數看一遍,觀察是否存在某個整數的平方等於 \(n\) 即可

第19 - 1題(3 分)

①處應填( )

A.1

B.2

C.3

D.4

題幹中提到,我們要找的 \(x\) 是一個正整數,所以迴圈 \(i\) 要從 \(1\) 開始

第19 - 2題(3 分)

②處應填( )

A.(int)floor(sqrt(num))-1

B.(int)floor(sqrt(num))

C.floor(sqrt(num/2))-1

D.floor(sqrt(num/2))

這裡的 sqrt 表示取平方根,floor 表示向下取整

根據第 8 行迴圈條件可以判斷出 bound 變數表示的就是最大邊界,所以 bound 應該等於 \(\sqrt{\text{num}}\)

因為 bound 是整數,所以可以把 \(\lfloor \sqrt{\text{num}} \rfloor\) 交給它

四個選項中,只有 B 選項等於 \(\lfloor \sqrt{\text{num}} \rfloor\)

第19 - 3題(3 分)

③處應填( )

A.num = 2 * i

B.num == 2 * i

C.num = i * i

D.num == i * i

現在是假設迴圈變數 \(i\) 就是我們要找的 \(x\)

所以要判斷的是 \(i^2 = \text{num}\) 是否成立

第19 - 4題(3 分)

④處應填( )

A.num = 2 * i

B.num == 2 * i

C.true

D.false

選完第三個空之後,發現只要第三個空的條件成立,就說明 num 是一個完全平方數

根據題意,這裡直接 return true 即可

第19 - 5題(3 分)

⑤處應填( )

A.num = i * i

B.num != i * i

C.true

D.false

填完第四個空後,根據題意,如果迴圈結束後都沒有執行任何一次 return true,就說明 \(1 \sim \sqrt{\text{num}}\) 中找不到任何一個數字的平方等於 \(\text{num}\),此時直接 return false 即可

第20 題 (15 分)

(漢諾塔問題)

給定三根柱子,分別標記為 A、B 和 C。初始狀態下,柱子 A 上有若干個圓盤,這些圓盤從上到下按從小到大的順序排列。任務是將這些圓盤全部移到柱子 C 上,且必須保持原有順序不變。在移動過程中,需要遵守以下規則:

  1. 只能從一根柱子的頂部取出圓盤,並將其放入另一根柱子的頂部。
  2. 每次只能移動一個圓盤。
  3. 小圓盤必須始終在大圓盤之上。

試補全程式。

一道非常經典的漢諾塔題目

以及

一份非常經典的漢諾塔程式碼

為了能把 src 上的 \(i\) 個盤子移動到 tgt 上,我們可以藉助遞迴分三步走:

  • 先把起始柱 src 上面的 \(i-1\) 個盤子先借助 tgt 移動到中間柱 tmp
    • 移動完成後,目標柱 tgt 為空
  • 再把最大的這個盤子從 src 移動到 tgt
    • 移動完成後,起始柱 src 為空
  • 再把第一步中的 \(i-1\) 個盤子藉助 src 移動到目標柱 tgt

move(src, tgt) 函式就表示執行一次移動,從 src 移動到 tgt

dfs(i, src, tmp, tgt) 表示遞迴,將 \(i\) 個盤子從 src 移動到 tgt 上,中間柱是 tmp

第20 - 1題(3 分)

①處應填( )

A.0

B.1

C.2

D.3

明顯僅當只剩一個盤子的時候,可以執行一次第 10 行的 move,然後結束遞迴

(如果條件裡面沒有 move 直接 return 了,應當對應無盤子的情況,要選 i == 0

第20 - 2題(3 分)

②處應填( )

A.src, tmp

B.src, tgt

C.tmp, tgt

D.tgt, tmp

只剩一個盤子時,直接從 src 移動到 tgt 即可,不用管 tmp

第20 - 3題(3 分)

③處應填( )

A.src, tmp, tgt

B.src, tgt, tmp

C.tgt, tmp, src

D.tgt, src, tmp

三步走中的第一步,先把 \(i-1\) 個盤子從 src 開始,藉助 tgt 移動到 tmp

第20 - 4題(3 分)

④處應填( )

A.src, tmp, tgt

B.tmp, src, tgt

C.src, tgt, tmp

D.tgt, src, tmp

三步走中的第三步,要把第一步移動到 tmp 上的 \(i-1\) 個盤子,再從 tmp 開始,藉助 src 移動到 tgt

第20 - 5題(3 分)

⑤處應填( )

A.0

B.1

C.i - 1

D.i

同上