【C++】B2069 求分数序列和题目解析与优化详解
文章目录
- 💯前言
- 💯题目描述
- 输入格式
- 输出格式
- 输入输出样例
- 输入:
- 输出:
- 💯解题思路
- 分析题目
- 解题步骤
- 💯代码实现
- 我的代码实现
- 实现特点
- 老师的代码实现
- 实现特点
- 优点
- 缺点
- 💯对比分析
- 💯优化方案
- 改进点
- 💯小结
💯前言
- 本篇文章将详细解析洛谷B2069题“求分数列和”的解题过程,包括题目的详细描述、解题思路、不同代码实现方案的比较与优化,以及对相关概念的深入拓展。文章的目标是帮助读者全面掌握此类题目的解法,并提升在C++编程中的逻辑分析与代码优化能力。
C++ 参考手册
💯题目描述
B2069 求分数序列和
有一个分数序列:
q 1 p 1 , q 2 p 2 , q 3 p 3 , q 4 p 4 , ⋯ \frac{q_1}{p_1}, \frac{q_2}{p_2}, \frac{q_3}{p_3}, \frac{q_4}{p_4}, \cdots p1q1,p2q2,p3q3,p4q4,⋯
其中,满足递推关系:
- q i + 1 = q i + p i q_{i+1} = q_i + p_i qi+1=qi+pi
- p i + 1 = q i p_{i+1} = q_i pi+1=qi
- 初始值 q 1 = 2 q_1 = 2 q1=2, p 1 = 1 p_1 = 1 p1=1。
例如,前6项依次为:
2 1 , 3 2 , 5 3 , 8 5 , 13 8 , 21 13 \frac{2}{1}, \frac{3}{2}, \frac{5}{3}, \frac{8}{5}, \frac{13}{8}, \frac{21}{13} 12,23,35,58,813,1321
任务是计算分数序列前 n n n 项的和。结果保留4位小数。
输入格式
输入一行包含一个正整数 n n n( n ≤ 30 n \leq 30 n≤30)。
输出格式
输出一行浮点数,表示分数序列前 n n n 项之和,精确到小数点后4位。
输入输出样例
输入:
2
输出:
3.5000
💯解题思路
分析题目
-
递推关系:
- 序列的分子和分母满足递推关系:
q i + 1 = q i + p i q_{i+1} = q_i + p_i qi+1=qi+pi
p i + 1 = q i p_{i+1} = q_i pi+1=qi - 初始条件为 q 1 = 2 q_1 = 2 q1=2, p 1 = 1 p_1 = 1 p1=1。
- 序列的分子和分母满足递推关系:
-
目标:
- 计算前 n n n 项的分数和:
sum = q 1 p 1 + q 2 p 2 + ⋯ + q n p n \text{sum} = \frac{q_1}{p_1} + \frac{q_2}{p_2} + \cdots + \frac{q_n}{p_n} sum=p1q1+p2q2+⋯+pnqn
- 计算前 n n n 项的分数和:
-
数据范围:
- n ≤ 30 n \leq 30 n≤30,意味着序列递推和累加的规模较小,可以采用简单的迭代方式解决。
-
精度要求:
- 输出结果保留小数点后4位。
解题步骤
-
初始化变量:
- 定义两个变量分别表示分子 q q q 和分母 p p p。
- 定义一个变量 s u m sum sum 用于累加结果。
-
递推计算:
- 根据公式更新 q q q 和 p p p。
- 累加当前项的分数值: q p \frac{q}{p} pq。
-
输出结果:
- 使用浮点数输出,保留小数点后4位。
💯代码实现
我的代码实现
以下是我的代码实现:
#include <iostream>
#include <cstdio>
using namespace std;int main() {double sum = 0; // 累加和,双精度浮点数int n = 0, temp = 0;int z = 2, m = 1; // 初始化分子和分母cin >> n;for (int i = 0; i < n; i++) {sum += z * 1.0 / m; // 累加当前项temp = z; // 暂存当前分子z = z + m; // 计算新的分子m = temp; // 更新分母为旧的分子}printf("%.4lf", sum); // 输出结果,保留 4 位小数return 0;
}
实现特点
-
变量设计:
- 使用
z
表示当前分子,m
表示当前分母。 - 使用
temp
保存中间变量,避免覆盖数据。
- 使用
-
核心递推逻辑:
- q i + 1 = q i + p i q_{i+1} = q_i + p_i qi+1=qi+pi 用
z = z + m
实现。 - p i + 1 = q i p_{i+1} = q_i pi+1=qi 用
m = temp
实现。
- q i + 1 = q i + p i q_{i+1} = q_i + p_i qi+1=qi+pi 用
-
浮点数计算:
- 显式将
z / m
转换为浮点数计算,确保精度。
- 显式将
-
结果输出:
- 使用
printf
保留4位小数。
- 使用
老师的代码实现
以下是老师给出的代码实现:
#include <iostream>
#include <cstdio> // 用于 printf
using namespace std;int main() {int n = 0;cin >> n;float sum = 0; // 累加和,浮点类型float q = 2; // 初始化分子 qfloat p = 1; // 初始化分母 pfor (int i = 0; i < n; i++) {sum += q / p; // 累加当前项q = q + p; // 计算新的 qp = q - p; // 计算新的 p}printf("%.4f\n", sum); // 输出结果,保留 4 位小数return 0;
}
实现特点
-
变量优化:
- 直接使用
float
类型计算,避免临时变量。
- 直接使用
-
核心递推逻辑:
- 使用
q = q + p
和p = q - p
通过数学公式简化更新。
- 使用
-
结果输出:
- 同样使用
printf
保留4位小数。
- 同样使用
优点
-
代码简洁:
- 变量数量少,通过数学公式避免了中间变量。
-
逻辑紧凑:
- 更新
p
的方式非常简练,体现了数学上的优化。
- 更新
缺点
-
可读性较差:
p = q - p
的逻辑不够直观,对初学者不够友好。
-
精度问题:
- 使用
float
类型可能导致精度不足。
- 使用
💯对比分析
对比点 | 我的代码 | 老师的代码 |
---|---|---|
变量数量 | 多一个临时变量 temp | 仅用两个变量 q 和 p |
代码可读性 | 逻辑清晰,易于理解 | 数学简化逻辑不直观 |
浮点精度 | 使用 double ,精度更高 | 使用 float ,精度稍低 |
内存使用 | 稍高,多用了一个变量 | 更低,只用了必要的变量 |
实现复杂度 | 适中,易于实现和调试 | 较低,但对理解有一定要求 |
💯优化方案
结合两者的优点,我们可以进一步优化代码:
#include <iostream>
#include <iomanip> // 用于控制输出精度
using namespace std;int main() {int n;cin >> n;double sum = 0.0; // 使用 double 提高精度int q = 2, p = 1; // 分子和分母初始化for (int i = 0; i < n; i++) {sum += static_cast<double>(q) / p; // 显式类型转换q = q + p; // 直接更新分子p = q - p; // 通过差值更新分母}cout << fixed << setprecision(4) << sum << endl; // 使用现代化流输出return 0;
}
改进点
-
精度提升:
- 使用
double
类型以提高浮点运算的精度。
- 使用
-
代码简化:
- 去掉了临时变量,简化逻辑。
-
现代化风格:
- 使用
cout
和setprecision
替代printf
,更符合 C++ 标准。
- 使用
💯小结
本题主要考察递推关系的理解与实现能力,同时对浮点数精度控制和代码优化提出了要求。在解题过程中,我们需要:
- 明确数列的递推关系。
- 合理设计变量以实现递推计算。
- 结合题目需求选择合适的浮点类型与输出方式。
通过对不同代码实现方案的比较与优化,我们不仅学会了更高效的解题方法,还理解了代码设计中的权衡取舍。希望本文能为读者提供帮助,在未来的编程学习中取得更大的进步!