浙江大學 PAT 甲級/乙級「循環-10」題目要求計算特定分數序列前 N 項和。本文從遞推關係建模、迭代實現、遞歸替代方案、精度控制、邊界處理五個維度,提供完整解題框架與代碼範式。
a[n] = a[n-1] + a[n-2]設第 i 項為 num[i] / den[i],則:
num[1] = 2, den[1] = 1 num[i] = num[i-1] + den[i-1] den[i] = num[i-1]
驗證:
| i | num | den | 項值 | 累加和 |
|---|---|---|---|---|
| 1 | 2 | 1 | 2.0000 | 2.0000 |
| 2 | 3 | 2 | 1.5000 | 3.5000 |
| 3 | 5 | 3 | 1.6667 | 5.1667 |
| 4 | 8 | 5 | 1.6000 | 6.7667 |
| 5 | 13 | 8 | 1.6250 | 8.3917 |
#include <stdio.h>
int main() {
int N;
scanf("%d", &N);
double sum = 0.0;
int num = 2, den = 1; // 第一項
for (int i = 1; i <= N; i++) {
sum += (double)num / den;
// 更新下一項分子分母
int next_num = num + den;
int next_den = num;
num = next_num;
den = next_den;
}
printf("%.2f\n", sum);
return 0;
}
#include <stdio.h>
float series_sum(int n) {
if (n == 1) return 2.0f; // 基例
// 遞歸計算前 n-1 項和,再加第 n 項
// 需輔助函數計算第 n 項值
return series_sum(n-1) + term_value(n);
}
float term_value(int n) {
if (n == 1) return 2.0f;
if (n == 2) return 1.5f;
// 實際需傳遞分子分母或用全局狀態,遞歸不適合此題
return 0; // 佔位
}
評價: 遞歸此處屬於「為遞歸而遞歸」,增加函數調用開銷且難維護狀態,不推薦實戰使用。
#include <stdio.h>
int main() {
int N;
scanf("%d", &N);
double sum = 0;
double a = 2.0, b = 1.0; // 用 double 直接存分子分母,避免轉換
for (int i = 0; i < N; i++) {
sum += a / b;
double next_a = a + b;
b = a;
a = next_a;
}
printf("%.2f\n", sum);
return 0;
}
| 風險 | 分析 | 對策 |
|---|---|---|
| 整數溢出 | N>46 時 Fibonacci 超過 int 範圍 | 用 double 存儲分子分母,或 long long 延遲溢出 |
| 浮點精度 | double 52 位尾數,N=100 相對誤差 ~1e-15 | 足夠滿足「保留 2 位小數」要求 |
| 輸出格式 | %.2f 四捨五入 | 確保包含 stdio.h,C99 標準行為一致 |
# N=1 輸入: 1 輸出: 2.00 # N=2 輸入: 2 輸出: 3.50 # N=10 輸入: 10 輸出: 16.48 # 手工驗證前10項和 # N=0 (若題目允許) 輸入: 0 輸出: 0.00 # 循環 0 次,sum 保持 0
a/b, c/dlong double 或大數庫#include <stdio.h>
int main() {
int N;
if (scanf("%d", &N) != 1) return 0; // 輸入驗證
double sum = 0;
double num = 2, den = 1;
for (int i = 0; i < N; i++) {
sum += num / den;
double tmp = num;
num = num + den;
den = tmp;
}
printf("%.2f\n", sum);
return 0;
}
分數序列求和是「遞推建模 + 迭代實現 + 精度控制」三位一體的經典訓練場。掌握雙變量滾動更新模式,可輕松應對斐波那契、兔子繁殖、樓梯跳躍等同構問題。建議動手對比 int/double/long long 三種類型在 N=50 時的表現,體會數值計算的工程權衡。