# APCS 2017-03-04 觀念題 詳解 ###### tags: `APCS` [APCS 模擬試卷 2017-03-04 觀念題](https://apcs.csie.ntnu.edu.tw/wp-content/uploads/2018/12/1060304APCSconcept.pdf)的詳解。 ## 第 1 題 此函式使用了二分搜尋法,可以在已排序的陣列中找到「大於 `x` 的最小值」。然而這個函式沒有進行例外處理 (exception handling),它沒有考慮到如果給定的 `x` 已經大於陣列中的最大值時,不可能可以找到「大於 `x`」 的數字。因此,如果傳入一個大於陣列中最大值的數字時,函式只會回傳陣列當中的最大值,並不滿足「**大於 `x` 的**最小值」這樣的條件,因此答案為 (D) 選項。 ## 第 2 題 `A1` 和 `A2` 都用到了 `F`, 所以必須先拆解 `F` 看看他會做什麼。 `F` 是一個遞迴函式,他會先印出 `x` 個星星,再執行 `F(x / 2)` 兩次,因此我們可以用以下遞迴式計算 `F(x)` 會印出的星星數量: $$F(x) = x + F(\lfloor\frac{x}{2}\rfloor) \times 2$$ 要注意的是,此處的除法都是指整數除法(因為 `x` 被宣告為 `int`), 因此除法的結果只取商,也就是無條件捨去的除法。所以上方式子中的 $\frac{x}{2}$ 必須加上下高斯符號。 依照上式,我們可以手動算出 `F(x)` 在不同參數時會印出的星星數量 ``` F(1) = 1 F(2) = 2 + F(1) * 2 = 2 + 1 * 2 = 4 F(3) = 3 + F(1) * 2 = 3 + 1 * 2 = 5 F(4) = 4 + F(2) * 2 = 4 + 4 * 2 = 12 F(5) = 5 + F(2) * 2 = 5 + 4 * 2 = 13 F(6) = 6 + F(3) * 2 = 6 + 5 * 2 = 16 F(7) = 7 + F(3) * 2 = 7 + 5 * 2 = 17 F(8) = 8 + F(4) * 2 = 8 + 12 * 2 = 32 F(9) = 9 + F(4) * 2 = 9 + 12 * 2 = 33 F(10) = 10 + F(5) * 2 = 10 + 13 * 2 = 36 F(11) = 11 + F(5) * 2 = 11 + 13 * 2 = 37 F(12) = 12 + F(6) * 2 = 12 + 16 * 2 = 44 ... ``` 接著回來看 `A1` 和 `A2`, 我們會發現 `A1` 和 `A2` 都是呼叫了 `F` 兩次,但參數有所不同。現在我們已經知道 `F` 在帶入不同數字時會印出多少星星了,因此就不難求出 `A1` 和 `A2` 會印出幾個星星。 * (A) 選項 * `A1(5) = F(1) + F(4) = 1 + 12 = 13` * `A2(5) = F(2) + F(3) = 4 + 5 = 9` * `A1(5) > A2(5)`, 此選項正確 * (B) 選項 * `A1(13) = F(2) + F(10) = 4 + 36 = 40` * `A2(13) = F(5) + F(7) = 13 + 17 = 30` * `A1(13) > A2(13)`, 此選項正確 * \(C\) 選項 * `A1(14) = F(2) + F(11) = 4 + 37 = 41` * `A2(14) = F(5) + F(8) = 13 + 32 = 47` * `A2(14) > A1(14)`, 此選項正確 * (D) 選項 * `A1(15) = F(3) + F(12) = 5 + 44 = 49` * `A2(15) = F(6) + F(9) = 16 + 33 = 49` * `A1(15) = A2(15)`, 此選項錯誤 因此答案為 (D) 選項。 ## 第 3 題 此題同樣是考遞迴概念,直接將各選項代入觀察輸出值即可。 * (A) 選項 * `F(14) = 14 * F(13) = 14 * 13 * F(12) = ... = 14 * 13 * 12 * ... * 3 != 40` * (B) 選項 * `F(14) = 14 + F(11) = 14 + 11 + F(8) = ... = 14 + 11 + 8 + 5 + 2 == 40` * \(C\) 選項 * `F(14) = 14 - F(12) = 14 - (12 - F(10)) = ... = 14 - 12 + 10 - 8 + 6 - 4 + 2 != 40` * (D) 選項 * 語法錯誤 (應為 `F(3 * n + 1)`) 因此答案為 (B) 選項。 ## 第 4 題 本題的觀念為輾轉相除法,請自行參閱[維基百科的說明頁面](https://zh.wikipedia.org/zh-tw/%E8%BC%BE%E8%BD%89%E7%9B%B8%E9%99%A4%E6%B3%95)。 ## 第 5 題 此段程式碼同時進行了兩個線性搜尋: `p` 是用來尋找陣列中的最大值; `q` 則是用來搜尋陣列中最小值。兩者皆以第一個元素為比大小的基準,然後看過剩下的 `n - 1` 個元素,遇到比當前記錄的值更大 / 更小的值時就取代掉當前值。因此,選項 (A), (B) 的敘述無誤。 但是題目並沒有保證 `A` 當中的數字不會重複, 如果我在陣列中存入 `n` 個一樣的數字,那麼最大值就會等於最小值,因此 \(C\) 選項不一定會成立。反之, (D) 選項有考慮到最大值可能大於,或是等同於第一個值的情況,因此絕對是正確的。 綜合以上分析,因此答案為 \(C\) 選項。 ## 第 6 題 此段程式碼的 `rowsum` 是想要用來代表每一列的總和,那麼初始化(設定為 0) 的動作就必須要在每一行開始加總前進行,而不是在整個函式中只初始化一次。如果按照當前寫法, `rowsum` 鎂一次被印出時,印出的值會是「第 j 列**以前**的所有列中的數字總和」,而不是「第 j 列的數字總和」。除此之外,本函式並沒有語法上的錯誤或是會造成 runtime error 的錯誤,因此答案為 (A) 選項。 ## 第 7 題 此段程式碼會以[巴斯卡三角形](https://zh.wikipedia.org/wiki/%E6%9D%A8%E8%BE%89%E4%B8%89%E8%A7%92%E5%BD%A2)的方式計算組合數 $C^n_k$。 ``` B(5, 2) = B(4, 1) + B(4, 2) = B(3, 0) + B(3, 1) + B(3, 1) + B(3, 2) = 1 + B(2, 0) + B(2, 1) + B(2, 0) + B(2, 1) + B(2, 1) + B(2, 2) = 1 + 1 + B(1, 0) + B(1, 1) + 1 + B(1, 0) + B(1, 1) + B(1, 0) + B(1, 1) + 1 = 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 ``` 最後有 10 個 1, 因此會印出 10 次。 或者說,用巴斯卡三角形算組合數的時候,所有數字都是由邊邊上的 1 堆出來的,所以直接算 $C^5_2 = 10$, 即可得知會印出 10 次,因此答案為 (D) 選項。 ## 第 8 題 拆解程式執行順序如下: ``` (global) s = 1; printf("%d,", s); // 1, // a = 1, 執行迴圈 (local) s = 6; printf("%d,", s); // 6, (local) s++; printf("%d,", s); // 7, // a = 0, 執行迴圈 printf("%d,", s); // 7, (local) s++; printf("%d,", s); // 8, // a = -1, 結束迴圈 (global) s = 1; printf("%d,", s); // 1, (global) s = 9; printf("%d", s); // 9 ``` 同樣名字的區域變數會遮蔽掉全域變數,因此在 `add` 函式中所有對 `s` 的運算以及印出的 `s` 值指的都是 `add` 函式內的 `s`, 不是全域的 `s`。 同時, C 語言在傳入 `int` 型態的參數時採用的是 call by value 的策略,因此全域 `s` 被傳入 `add` 中當作 `a` 時,在 `add` 裏面對 `a` 的運算並不會改變全域 `s` 原本的值。因此,在 `add` 函式返回後, 全域 `s` 的值仍舊是 1。 而在 main function 中因為沒有別的叫作 `s` 的變數了,因此在 main function 中改變 `s` 的值時,變更的會是全域 `s` 的值。 綜合以上分析,可以得知印出的數列為 `1,6,7,7,8,1,9` 答案為 (B) 選項。 ## 第 9 題 此段程式碼會將輸入的數字依序存入 `X[2]`, `X[3]`, `X[4]`, `X[5]`, `X[6]`, `X[7]`, `X[8]`, `X[9]`, `X[0]`, `X[1]` 中。 如果輸入依序是 `0 1 2 3 4 5 6 7 8 9` 的話,那麼 ``` X[2] X[3] X[4] X[5] X[6] X[7] X[8] X[9] X[0] X[1] 0 1 2 3 4 5 6 7 8 9 ``` 等同於 ``` X[0] X[1] X[2] X[3] X[4] X[5] X[6] X[7] X[8] X[9] 8 9 0 1 2 3 4 5 6 7 ``` 因此答案為 (D) 選項。 ## 第 10 題 `K` 函式的行為在傳入的參數不同時有不同行為: * 當傳入的參數除以 4 餘 0 時,他只會做 1 次的 `n = n + 1` * 當傳入的參數除以 4 餘 1 時,他會透過遞迴呼叫做 4 次的 `n = n + 1` * 當傳入的參數除以 4 餘 2 時,他會透過遞迴呼叫做 3 次的 `n = n + 1` * 當傳入的參數除以 4 餘 3 時,他會透過遞迴呼叫做 2 次的 `n = n + 1` `M` 函式透過迴圈呼叫了 100 次的 `K`, 傳入的參數當中,除以 4 餘 0、 餘 1、 餘 2、 餘 3 的分別有 25 個,因此 `n` 會被增加 $25 \times 1 + 25 \times 4 + 25 \times 3 + 25 \times 2 = 250$ 次,最後 `n` 的值會是 250, 答案為 (D) 選項。 ## 第 11 題 * (A)選項 * `A[1] = A[2];` 此時 `A[1]` 的值已經是 `A[2]` 的值 * `A[2] = A[1];` 用 `A[2]` 的值覆蓋掉 `A[2]` * 最後 `A[1]`, `A[2]` 的值都是 `A[2]` 原本的值 * (B)選項 * `A[3] = A[1];` 使用 `A[3]` 當作暫存空間,儲存 `A[1]` 原本的值 * `A[1] = A[2];` 由於 `A[1]` 的值已經借放在 `A[3]` 了,所以可以放心的用 `A[2]` 的值覆蓋掉 * `A[2] = A[3];` 把 `A[1]` 原本的值放入 `A[2]` 中 * 成功交換了 `A[1]` 和 `A[2]` 中的值 * \(C\)選項 * `A[2] = A[1];` 將 `A[1]` 的值存入 `A[2]` * `A[3] = A[2];` 將 `A[2]` 的值,也就是原本 `A[1]` 的值存入 `A[3]` * `A[1] = A[3];` 用 `A[1]` 的值覆蓋掉 `A[1]` * 最後 `A[1]`, `A[2]`, `A[3]` 的值都是 `A[1]` 原本的值 * (D)選項 * 只有 (B) 是對的 因此答案為 (B) 選項。 ## 第 12 題 此題的要求是「產生在 $[100, 1000]$ 範圍內的亂數」, 1000 - 100 + 1 = 901, 我們可以得知在這個範圍內總共有 901 種數字。將 `rand()` 的輸出除以 901 取餘數,可以得到餘數的範圍在 $[0, 900]$, 總共也是 901 種數字,但是跟需要的範圍差了 100 的 bias, 因此需要再往右位移 100, 也就是加上 100 的意思。總結以上, `rand() % 901 + 100` 產生出來的數字範圍就會落在 $[100, 1000]$ 的範圍內,答案為 (D) 選項。 題外話,雖然題目有說 `rand()` 產生出的亂數範圍在 $[0, 10000]$, 總共有 10001 種數字。但我們需要的只有 901 種數字,所以只要 `rand()` 可以產生大於 901 種數字,無論範圍在哪裡其實都無所謂。 ## 第 13 題 此段程式碼的迴圈在 `i` 值為 0, 5, 10, 15, ..., 95, 100 時會執行迴圈本體,總共會執行 21 次(因為 0, 5, ..., 100 共有 21 個數字)。 * (A) 選項 * 如果上界改為 20 (沒有等於),且每次只 +1 的話,那麼在 `i` 值為 0, 1, 2, ..., 19 時會執行迴圈本體,總共會執行 20 次 * (B) 選項 * 如果將初始值設定為 5, 那麼在 `i` 值為 5, 10, 15, ..., 100 時會執行迴圈本體,總共會執行 20 次 * \(C\) 選項 * 如果上界改為 100 (沒有等於),那麼在 `i` 值為 0, 5, 10, 15, ..., 95 時會執行迴圈本體,總共會執行 20 次 * (D) 選項 * 如果將初始值設定為 5, 且上界改為 100 (沒有等於)的話,那麼在 `i` 值為 5, 10, 15, ..., 95 時會執行迴圈本體,總共只會執行 **19** 次 因此答案為 (D) 選項。 ## 第 14 題 分析程式執行的順序: ```c= F(15); // F(15) printf ("%d\n" , 15); return F(76); // (15 % 2 == 1) && (15 > 1) // F(76) printf ("%d\n" , 76); return F(38); // (76 % 2 == 0) // F(38) printf ("%d\n" , 38); return F(19); // (38 % 2 == 0) // F(19) printf ("%d\n" , 19); return F(96); // (19 % 2 == 1) && (19 > 1) // F(96) printf ("%d\n" , 96); return F(48); // (96 % 2 == 0) // F(48) printf ("%d\n" , 48); return F(24); // (48 % 2 == 0) // F(24) printf ("%d\n" , 24); return F(12); // (24 % 2 == 0) // F(12) printf ("%d\n" , 12); return F(6); // (12 % 2 == 0) // F(6) printf ("%d\n" , 6); return F(3); // (6 % 2 == 0) // F(3) printf ("%d\n" , 3); return F(16); // (3 % 2 == 1) && (3 > 1) // F(16) printf ("%d\n" , 16); return F(8); // (16 % 2 == 0) // F(8) printf ("%d\n" , 8); return F(4); // (8 % 2 == 0) // F(4) printf ("%d\n" , 4); return F(2); // (4 % 2 == 0) // F(2) printf ("%d\n" , 2); return F(1); // (2 % 2 == 0) // F(1) printf ("%d\n" , 1); // (1 % 2 == 1) but !(1 > 1), and !(1 % 2 == 0), no action ``` 總共印出了 15 行的數字,答案為 (D) 選項。 ## 第 15 題 ```c= void F (int a) { while (a < 10) a = a + 5; if (a < 12) a = a + 2; if (a <= 11) a = 5; } ``` 1. 在 `a < 10` 的情況下,會藉由第 2 行的 `while` 迴圈將 `a` 加到大於 10。 所以 1. 與 5 同餘 1 的數字(如 6, 1, -4, ...) 會變成 11 2. 與 5 同餘 2 的數字(如 7, 2, -3, ...) 會變成 12 3. 與 5 同餘 3 的數字(如 8, 3, -2, ...) 會變成 13 4. 與 5 同餘 4 的數字(如 9, 4, -1, ...) 會變成 14 5. 可以被 5 整除的數字(如 5, 0, -5...) 會變成 10 2. 在 `a == 10` 或 `a == 11`, 以及 1.1 和 1.5 的情況下,第 4 行的 `if` 本體將會把 `a` 改動成 12 或 13, 因此無法進入第 6 行的 `if` 本體 3. 在 `a >= 12`, 以及 1.2, 1.3, 1.4 的情況下,第 4 行與第 6 行的 `if` 本體都不會被執行 以上的分析涵蓋了完整的整數範圍。由此可知,無論傳入的 `a` 是多少,永遠都不會進入第 6 行的 `if` 本體,因此 `a = 5` 永遠都不會被執行到,答案為 \(C\) 選項。 ## 第 16 題 `F(7)` 回傳值為 17, 表示是從 `a * 2 + 3` 計算得來的;而 `F(8)` 回傳值為 25, 表示是從 `a * 3 + 1` 計算得來的。因此, `if` 中的條件判斷式必須是 7 可以滿足 (結果為 `true`), 但 8 無法滿足 (結果為 `false`) 的條件。 * (A) 選項 * `7 % 2 != 1` 的結果為 `false` * `8 % 2 != 1` 的結果為 `true` * (B) 選項 * `7 * 2 > 16` 的結果為 `false` * `8 * 2 > 16` 的結果為 `false` * \(C\) 選項 * `7 + 3 < 12` 的結果為 `true` * `8 + 3 < 12` 的結果為 `true` * (D) 選項 * `7 * 7 < 50` 的結果為 `true` * `8 * 8 < 50` 的結果為 `false` 因此答案為 (D) 選項。 ## 第 17 題 ```c= int F (int n) { int x = 0; for (int i = 1; i <= n; i = i + 1) for (int j = i; j <= n; j = j + 1) for (int k = 1; k <= n; k = k * 2) x = x + 1; return x; } ``` 迴圈的執行必須從最內層分析到最外層。因此我們從第 5 行的迴圈開始看起: 0. `x` 從 0 開始累加 1. 第 5 行的迴圈每執行一次, `x` 就會增加 1 2. 第 5 行的迴圈每執行一次, `k` 就會變成原本的 2 倍,直到 `k` 超越 `n`, 才會停止執行迴圈。 `k` 一開始的值是 1,因此我們可以代入幾個 `n` 值推論第 5 行迴圈的執行次數 * $n \leq 1$ 時,迴圈只會執行 1 次 * $2 \leq n < 4$ 時,迴圈會執行 2 次(在這個範圍內的 `n`, 取 $log_2$ 後無條件進位,都會是 2) * $4 \leq n < 8$ 時,迴圈會執行 3 次(在這個範圍內的 `n`, 取 $log_2$ 後無條件進位,都會是 3) * $8 \leq n < 16$ 時,迴圈會執行 4 次(在這個範圍內的 `n`, 取 $log_2$ 後無條件進位,都會是 4) * ... * $2^{N - 1} \leq n < 2^N$ 時,迴圈會執行 $N$ 次(在這個範圍內的 `n`, 取 $log_2$ 後無條件進位,都會是 $N$) 也就是說,將傳入的 `n` 取 $log_2$ 後無條件進位,就是第 5 行迴圈的執行次數,即第 5 行迴圈會執行 $\lfloor log_2n + 1 \rfloor$ 次 3. 第 4 行迴圈每執行一次, `x` 就會增加 $\lfloor log_2n + 1 \rfloor$。 第 4 行迴圈的執行次數是由第 3 行迴圈的 `i` 所決定的: * 當 `i == 1` 時,第 4 行迴圈會執行 `n` 次 * 當 `i == 2` 時,第 4 行迴圈會執行 `n - 1` 次 * 當 `i == 3` 時,第 4 行迴圈會執行 `n - 2` 次 * 當 `i == 4` 時,第 4 行迴圈會執行 `n - 3` 次 * ... * 當 `i == n` 時,第 4 行迴圈會執行 1 次 因此,第 3, 4 行的雙層迴圈總共會執行 $1 + 2 + 3 + ... + n = \sum\limits_{i=1}^{n} i = \frac{n(n + 1)}{2}$ 次 因此,這三層迴圈總共會執行 $n(n + 1)\lfloor log_2n + 1 \rfloor/2$ 次,答案為 \(C\) 選項。 ## 第 18 題 分析每次迴圈本體執行時 `i`, `j` 的值為: ``` i = 1, j = 1: (i + j) == 2, x = x + 2 = 2 i = 1, j = 2: (i + j) == 3, x = x + 3 = 5 i = 1, j = 3: (i + j) == 4, x = x + 4 = 9 i = 1, j = 4: (i + j) == 5 i = 1, j = 5: (i + j) == 6 i = 2, j = 1: (i + j) == 3, x = x + 3 = 12 i = 2, j = 2: (i + j) == 4, x = x + 4 = 16 i = 2, j = 3: (i + j) == 5 i = 2, j = 4: (i + j) == 6 i = 2, j = 5: (i + j) == 7 i = 3, j = 1: (i + j) == 4, x = x + 4 = 20 i = 3, j = 2: (i + j) == 5 i = 3, j = 3: (i + j) == 6 i = 3, j = 4: (i + j) == 7 i = 3, j = 5: (i + j) == 8 i = 4, j = 1: (i + j) == 5 i = 4, j = 2: (i + j) == 6 i = 4, j = 3: (i + j) == 7 i = 4, j = 4: (i + j) == 8 i = 4, j = 5: (i + j) == 9 i = 5, j = 1: (i + j) == 6 i = 5, j = 2: (i + j) == 7 i = 5, j = 3: (i + j) == 8 i = 5, j = 4: (i + j) == 9 i = 5, j = 5: (i + j) == 10 ``` 因此輸出為 20, 答案為 (D) 選項。 ## 第 19 題 ```c= int main () { int M = -1, N = 101, s = 3; int A[] = ______?______; for (int i = 0; i < s; i = i + 1) { if (A[i] > M) { M = A[i]; } else if (A[i] < N) { N = A[i]; } } printf("M = %d, N = %d\n", M, N); return 0; } ``` 此段程式碼的錯誤點在於: 第 9 行是 `else if` 而不是 `if`, 這會造成 `A[i] < N` 只有在 `A[i] > M` 不成立的情況下才會執行。如果這個陣列是嚴格遞增的陣列(也就是每一個數字都比前面的數字還要大),那麼每一次進入迴圈 `A[i] > M` 永遠都會成立,第 9 行也就永遠都不會被執行到,也就是永遠都不會找到最小值 `N`。 因此答案為 (B) 選項。 ## 第 20 題 ```c= int g1 = 30, g2 = 20; int f1(int v) { int g1 = 10; return g1 + v; } int f2(int v) { int c = g2; v = v + c + g1; g1 = 10; c = 40; return v; } int main() { g2 = 0; g2 = f1(g2); printf("%d", f2(f2(g2))); return 0; } ``` 程式從 16 行開始執行,分析程式執行順序如下: 1. 由於 main function 內沒有定義叫作 `g2` 的變數,因此第 17 行的 `g2` 指的是第 1 行的全域變數 `g2`。 第 17 行會將該全域變數設定為 0 2. 第 18 行呼叫 `f1(g2)`,此時 `g2 == 0`, 也就是呼叫 `f1(0)`: 1. 進入 `f1`, 第 4 行宣告了一個叫作 `g1` 的區域變數,其值為 10。 由於同名的區域變數會覆蓋掉全域變數,因此第 1 行的全域變數 `g1` 其值不會受影響 2. 第 5 行回傳區域變數 `g1` 加上傳入參數 `v` 的值,也就是回傳 `10 + 0 = 10` 3. 回到第 18 行,此時全域變數 `g2` 被設定為 10 3. 第 19 行呼叫 `f2(f2(g2))`, 此時全域變數 `g2` 為 10, 也就是 `f2(f2(10))`: 1. 先解析內層的 `f2(10)`: 1. 第 9 行宣告區域變數 `c`, 並以全域變數 `g2` 賦值。此時 `g2 = 10`, 因此 `c = 10` 2. 第 10 行將傳入的參數 `v` 設定為 `v + c + g1`, 此時全域變數 `g1` 為 30, 因此 `v = 10 + 10 + 30 = 50` 3. 由於 `f2` 內沒有定義叫作 `g1` 的變數,因此第 11 行的 `g1` 指的是第 1 行的全域變數 `g1`。 第 11 行會將該全域變數設定為 10 4. 第 12 行將區域變數 `c` 設定為 40。 但因為回傳前都沒有再用到了,所以沒有影響 5. 回傳 `v`, 也就是回傳 50 2. 回到第 19 行,此時要解析外層的 `f2(50)` 1. 第 9 行宣告區域變數 `c`, 並以全域變數 `g2` 賦值。此時 `g2 = 10`, 因此 `c = 10` 2. 第 10 行將傳入的參數 `v` 設定為 `v + c + g1`, 此時全域變數 `g1` 為 10, 因此 `v = 50 + 10 + 10 = 70` 3. 由於 `f2` 內沒有定義叫作 `g1` 的變數,因此第 11 行的 `g1` 指的是第 1 行的全域變數 `g1`。 第 11 行會將該全域變數設定為 10 4. 第 12 行將區域變數 `c` 設定為 40。 但因為回傳前都沒有再用到了,所以沒有影響 5. 回傳 `v`, 也就是回傳 70 3. 回到第 19 行,此時全域變數 `g2` 為 70 4. 第 19 行 `printf` 印出 70 因此答案為 (A) 選項。 ## 第 21 題 ```c= int F (int x, int y) { if (x < 1) return 1; else return F(x - y, y) + F(x - 2 * y, y); } ``` 若以 `F(5, 2)` 呼叫此函式,分析函式執行順序如下: 1. 第 2 行, 5 沒有小於 1, 因此跳過第 3 行 2. 第 4 行, 執行 `F(x - y, y) + F(x - 2 * y, y)`, 代入 `x = 5` 和 `y = 2`, 也就是執行 `F(3, 2) + F(1, 2)` 1. 首先是 `F(3, 2)` 的部份 1. 第 2 行, 3 沒有小於 1, 因此跳過第 3 行 2. 第 4 行, 執行 `F(x - y, y) + F(x - 2 * y, y)`, 代入 `x = 3` 和 `y = 2`, 也就是執行 `F(1, 2) + F(-1, 2)` 1. 首先是 `F(1, 2)` 的部份 1. 第 2 行, 1 沒有小於 1, 因此跳過第 3 行 2. 第 4 行, 執行 `F(x - y, y) + F(x - 2 * y, y)`, 代入 `x = 1` 和 `y = 2`, 也就是執行 `F(-1, 2) + F(-3, 2)` 1. 首先是 `F(-1, 2)` 的部份,由於第 2 行中 -1 小於 1, 因此回傳 1 2. 再來是 `F(-3, 2)` 的部份,由於第 2 行中 -3 小於 1, 因此回傳 1 3. 第 4 行回傳 `1 + 1 = 2` 2. 再來是 `F(-1, 2)` 的部份,由於第 2 行中 -1 小於 1, 因此回傳 1 3. 第 4 行回傳 `2 + 1 = 3` 2. 再來是 `F(1, 2)` 的部份,從上述步驟可得知, `F(1, 2)` 會回傳 2 3. 第 4 行回傳 `3 + 2 = 5` 最後的回傳值為 5, 答案為 \(C\) 選項。 ## 第 22 題 1. `!(X1 || X2)` 為 `true`, 也就是 `X1 || X2` 為 `false` 2. `X1 || X2` 為 `false`, 只有在 `X1` 和 `X2` 皆為 `false` 的情況下才有可能成立 因此答案為 (A) 選項。 ## 第 23 題 計算機組織基本概念題,答案為 (A) 選項。 ## 第 24 題 程式設計(一)基本概念題,答案為 (A) 選項。 ## 第 25 題 此題探討的是運算子的優先度 (precedence), 優先度較高的運算子必須要先運算;如果優先度一樣,則由左至右計算。 在 C 語言中,乘除 (`*`, `/`, `%`) 的優先度高於加減 (`+`, `-`)。 因此, `a + b * c - e` 應該被解析為 `a + (b * c) - e`。 而加減的優先度一樣,因此由左至右計算,也就是左邊要先算,應解析為 `((a + (b * c)) - e)`。 因此答案為 \(C\) 選項。 ## 討論區 如果有疑問,可以點選左上方的鉛筆符號或是雙頁符號,直接複製以下範例發問喔~ > 請問第 N 題的 XXX 為什麼會 OOO 呢? [name=kinoe_T]