114 高普考普通考試 資訊處理 程式設計概要 考古題詳解
第 一 題25 分
撰寫一個 Java 程式,使用遞迴計算給定正整數 的「卡塔蘭數」(Catalan Number)。
其中 定義為:
使用者輸入 ( 為非負整數且不超過 )。輸出 ,並使用 long 型別。
執行範例如下:例如輸入 ,輸出 。
請完成下列程式碼:
(一)完成(A)程式碼(12 分)
(二)完成(B)程式碼(3 分)
(三)完成(C)程式碼(3 分)
(四)完成(D)程式碼(4 分)
(五)完成(E)程式碼(3 分)
import java.util.InputMismatchException; import java.util.Scanner;
public class JP2 { public static long catalan(int n) { (A) return sum; }
public static void main(String[] args) {
Scanner scanner = (B)
int n;
try {
n = scanner.nextInt();
(C){
System.out.println("輸入不合法!");
scanner.close();
return;
}
} catch (InputMismatchException e) {
System.out.println("輸入不合法!");
scanner.close();
return;
}
(D)
System.out.println((E) + result);
scanner.close();
}
}
登入後即可作答並保存紀錄。
核心觀念
本題考遞迴函式、輸入合法性檢查,以及 long 型別的整數運算。
卡塔蘭數的定義為:
遞迴函式必須有終止條件:當 時回傳 ;當 時,依公式累加各組乘積。
解題方法
catalan 函式以 sum 儲存總和,初值設為 0。使用 for 迴圈令 從 到 ,將每一項 加入總和。當 時,直接回傳 ,避免進入迴圈。
輸入檢查則需確認 在 到 之間;若不符合,輸出錯誤訊息並結束程式。nextInt 遇到非整數輸入時會拋出 InputMismatchException,由 catch 處理。
各空格答案
(A)
if (n == 0) {
return 1L;
}
long sum = 0L;
for (int i = 0; i < n; i++) {
sum += catalan(i) * catalan(n - 1 - i);
}
return 1L 是遞迴終止條件。其餘情況逐項套用遞迴定義,並以 long 儲存累加結果。
(B)
new Scanner(System.in);
建立讀取標準輸入的 Scanner。
(C)
if (n < 0 || n > 15)
檢查輸入是否超出題目指定範圍。此處使用邏輯或 ||,代表小於 或大於 任一情況成立,就判定輸入不合法。
(D)
long result = catalan(n);
呼叫遞迴函式計算結果,並以 long 儲存。
(E)
"C(" + n + ")="
組成輸出標籤,例如 時,輸出文字為 C(4)=14。
關鍵推導與驗算
依定義逐步計算:
第 二 題25 分
依據以下 C 程式碼,回答下列問題:
(一)第 6~12 行程式碼功能(4 分)
(二)第 13~17 行程式碼功能(4 分)
(三)第 19~29 行程式碼功能(7 分)
(四)第 30~32 行程式碼功能(2 分)
(五)第 33~41 行程式碼功能(4 分)
(六)第 42~45 行程式碼功能(2 分)
(七)第 46~49 行程式碼功能(2 分)
程式碼如下:
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #define MAXWL 21
- #define MAXWS 100
- int c1(const char* s1, const char* s2) {
-
while (*s1 && *s1 == *s2) { -
s1++; -
s2++; - }
- return *s1 - *s2;
- }
- int c2(const char* s) {
-
int len = 0; -
while (s[len]) len++; -
return len; - }
- int main() {
-
char** words = malloc(MAXWS * sizeof(char*)); -
int count = 0; -
char buffer[MAXWL]; -
while (1) { -
if (fgets(buffer, MAXWL, stdin) == NULL) break; -
buffer[strcspn(buffer, "\n")] = '\0'; -
if (buffer[0] == '\0') break; -
words[count] = malloc(c2(buffer) + 1); -
strcpy(words[count], buffer); -
count++; -
} -
for (int i = 0; i < count; i++) { -
printf("Word: %s, Length: %d\n", words[i], c2(words[i])); -
} -
for (int i = 0; i < count - 1; i++) { -
for (int j = 0; j < count - i - 1; j++) { -
if (c1(words[j], words[j + 1]) > 0) { -
char* temp = words[j]; -
words[j] = words[j + 1]; -
words[j + 1] = temp; -
} -
} -
} -
printf("Sorted words:\n"); -
for (int i = 0; i < count; i++) { -
printf("%s\n", words[i]); -
} -
for (int i = 0; i < count; i++) { -
free(words[i]); -
} -
free(words); -
return 0; - }
登入後即可作答並保存紀錄。
核心觀念
本題考查 C 語言的字串表示與操作、動態記憶體配置、氣泡排序,以及記憶體釋放。C 字串以 '\0' 作為結尾標記;malloc 配置記憶體,free 釋放記憶體。
解題方法與各小題
(一)第 6~12 行:自訂字串比較函式 c1
逐字比較 s1 和 s2 指向的字元。當兩個字元相同且尚未遇到字串結尾時,兩個指標各往後移一個字元。迴圈結束後回傳 *s1 - *s2:
- 回傳值小於 0:
s1字典序小於s2。 - 回傳值等於 0:兩字串相同。
- 回傳值大於 0:
s1字典序大於s2。
若其中一個字串是另一個字串的前綴,較短字串的結尾字元 '\0' 小於另一字串接續的字元,因此較短字串排在前面。這個函式的比較方式與 strcmp 類似。
(二)第 13~17 行:自訂字串長度函式 c2
從索引 0 開始,逐一檢查 s[len];遇到 '\0' 前,每次將 len 加 1。最後回傳 len,也就是字串長度。
長度不包含結尾的 '\0'。例如字串 "cat" 的長度是 3,但儲存時需要 4 個字元位置,包含結尾標記。
(三)第 19~29 行:讀取輸入並動態儲存字串
- 第 19 行以
malloc配置可容納MAXWS個char*的陣列,words用來存放各字串的位址。 - 第 20 行將字串數量
count設為 0;第 21 行建立可容納MAXWL個字元的輸入緩衝區。 - 第 22~23 行反覆讀取一行輸入。若
fgets回傳NULL,代表讀取失敗或遇到檔案結尾,便停止讀取。 - 第 24 行以
strcspn找出換行字元'\n'的位置,並以'\0'取代,移除輸入字串尾端的換行符號。 - 第 25 行若讀到空字串,就停止輸入。
- 第 26 行依目前字串長度加上結尾標記所需空間,配置字串記憶體。長度為 時,配置 個位元組。
- 第 27~28 行將緩衝區內容複製到新配置的記憶體,並將字串數量加 1。
第 三 題25 分
依據以下 Python 程式碼,回答下列問題:
(一)第 2~8 行程式碼功能(4 分)
(二)第 10~12 行程式碼功能(3 分)
(三)第 14~15 行程式碼功能(4 分)
(四)第 17~20 行程式碼功能(4 分)
(五)第 22~24 行程式碼功能(3 分)
(六)第 26~29 行程式碼功能(4 分)
(七)第 31~32 行程式碼功能(3 分)
程式碼如下:
- def main():
-
x = [] -
for _ in range(3): -
r = list(map(int, input().split())) -
if len(r) != 3: -
print("輸入不合法!") -
return -
x.append(r) - print("運算前資料:")
- for r in x:
-
print(" ".join(f"{x:5d}" for x in r)) - sdm = sum(x[i][2 - i] for i in range(3))
- print(f"sdm: {sdm}")
- y = [[0] * 3 for _ in range(3)]
- for i in range(3):
-
for j in range(3): -
y[j][2 - i] = x[i][j] - print("運算後資料:")
- for r in y:
-
print(" ".join(f"{x:5d}" for x in r)) - for i, r in enumerate(y):
-
rs = sum(r) -
ra = rs // len(r) -
print(f"R{i}: rs = {rs}, ra = {ra}") - if name == "main":
-
main()
登入後即可作答並保存紀錄。
核心觀念
本題考查 Python 的串列(list)、輸入資料驗證、生成式與索引運算、二維串列的轉置與反斜對角線加總,以及整數除法。
輸入資料 x 與輸出資料 y 都是 的二維串列。串列索引從 開始,因此元素 x[i][j] 表示第 i 列、第 j 欄。
解題方法與各段功能
(一)第 2~8 行:讀入並驗證三列資料(4 分)
x = [] 建立空串列,用來存放輸入的矩陣。for _ in range(3) 讓程式重複讀取三列;底線 _ 表示迴圈計數值不會在迴圈中使用。
第 4 行將一列輸入以空白切分,再逐一轉為整數,組成串列 r。例如輸入 1 2 3,會得到 r = [1, 2, 3]。
第 5~7 行檢查該列是否恰有三個數值;若數量不是 3,就印出「輸入不合法!」並以 return 結束 main。通過檢查後,第 8 行將該列加入 x。
因此,此段在讀入並驗證一個有三列、每列三個整數的 矩陣。
(二)第 10~12 行:印出運算前資料(3 分)
第 10 行印出標題。第 11 行逐列取出 x 中的串列 r;第 12 行將該列各整數以欄寬 5 格的格式輸出,並以空白串接。
格式 :5d 表示將整數以十進位輸出,欄寬至少為 5;" ".join(...) 則將格式化後的各數字以空白連接。
(三)第 14~15 行:計算並輸出反斜對角線總和(4 分)
第 14 行以 sum 加總 x[i][2 - i],其中 i 依序為 0、1、2,因此取到:
這是由右上角到左下角的反斜對角線元素總和。第 15 行以 f-string 印出變數 sdm 的值。
例如矩陣為
則 sdm = 3 + 5 + 7 = 15。
(四)第 17~20 行:建立並填入轉置矩陣(4 分)
第 17 行建立一個 、元素初值皆為 0 的二維串列 y。外層與內層各建立三個元素。
第 18~20 行以雙層迴圈逐一處理 x[i][j],並執行:
這不是一般的轉置,而是將原矩陣順時針旋轉 。例如原矩陣為
第 四 題25 分
依據以下 C# 程式碼,回答下列問題:
(一)第 6~19 行程式碼功能(9 分)
(二)第 20~31 行程式碼功能(8 分)
(三)此程式輸出結果為何?(8 分)
程式碼如下:
- using System;
- namespace CSP4
- {
-
class Program -
{ -
static bool CSP4_1(int x) -
{ -
if (x < 0) return false; -
int L = 0, R = x; -
while (L <= R) -
{ -
int M = L + (R - L) / 2; -
long S = (long)M * M; -
if (S == x) return true; -
else if (S < x) L = M + 1; -
else R = M - 1; -
} -
return false; -
} -
static long CSP4_2(int n) -
{ -
if (n <= 1) return n; -
long a = 0, b = 1; -
for (int i = 2; i <= n; i++) -
{ -
long temp = a + b; -
a = b; -
b = temp; -
} -
return b; -
} -
static void Main() -
{ -
int[] arrays = { 9, 10, -4 }; -
foreach (var n in arrays) -
{ -
Console.WriteLine($"{n} is CSP4_1? {CSP4_1(n)}"); -
Console.WriteLine($"CSP4_2({n}) = {CSP4_2(n)}"); -
} -
} - }
- }
登入後即可作答並保存紀錄。
核心觀念
本題考查兩種常見演算法:
- 二分搜尋法:將可能的整數答案範圍反覆折半,判斷是否存在整數平方根。
- 費波那契數列:利用迴圈逐項計算,並以兩個變數保存前兩項,避免遞迴呼叫。
(一)第 6~19 行程式碼功能
CSP4_1(int x) 用來判斷整數 是否為非負整數的完全平方數,是則回傳 true,否則回傳 false。
解法使用二分搜尋法:
- 若 ,負數不可能是整數平方,直接回傳
false。 - 對 ,設定搜尋範圍 、。
- 每次取中間值 ,並計算 。
- 若 ,表示找到整數平方根,回傳
true。 - 若 ,平方根在右側,令 。
- 若 ,平方根在左側,令 。
- 範圍縮至空集合仍未找到時,回傳
false。
第 13 行先將 M 轉成 long 再相乘,可避免兩個 int 相乘時發生整數溢位。
(二)第 20~31 行程式碼功能
CSP4_2(int n) 計算並回傳第 項費波那契數列。數列定義為: