1 条题解
-
0
有理分数逼近问题题解
题目分析
问题描述:给定浮点数和整数,寻找分子和分母(),使得分数与的绝对误差最小。若存在多个解,输出其中任意一个。
输入格式:输入包含浮点数和整数()。
输出格式:输出最优分数的分子和分母 。算法思路
该问题属于有理分数逼近问题,代码采用贪心调整策略逐步寻找最优解:
- 初始化分子和分母,从最小分数开始搜索。
- 比较当前分数与目标值的大小:
- 若,则增大分子(使分数接近)。
- 若,则增大分母(使分数减小)。
- 每次调整后计算误差,记录误差最小的分数作为最优解。
代码关键步骤
- 初始化:分子和分母从开始,误差初始化为较大值(如)。
- 循环调整:
- 计算当前分数。
- 若,说明分数偏小,增大分子以接近。
- 若,说明分数偏大,增大分母以减小分数。
- 误差记录:每次调整前比较误差,若当前误差更小,则更新最优解和。
示例分析
输入:
- 初始,分数,增加到。
- 分数,增加到()。
- 时,,改为增大到,分数,增加到()。
- 继续调整,最终在时,分数,误差较小,成为最优解。
复杂度分析
- 时间复杂度:,最坏情况下需遍历和从到,总循环次数为。
- 空间复杂度:,仅使用常数级变量。
关键点
- 贪心策略:通过动态调整分子和分母,使分数逐步逼近目标值,适用于较小的场景。
- 误差比较:每次调整前更新最小误差,确保记录最优解。
- 边界条件:当或超过时终止循环,保证分数的分子和分母不超过限制。
标程
#include <iostream> using namespace std; int main(){ double a, tmp, min = 16; int top, bottom, L, ans_n, ans_d; cin >> a >> L; top = bottom = 1; while (top <= L && bottom <= L) { tmp = (double)top / bottom; if (tmp < a) { if (a - tmp < min) { // 误差更小则更新最优解 min = a - tmp; ans_n = top; ans_d = bottom; } top++; // 分数小于a时增大分子 } else { if (tmp - a < min) { // 误差更小则更新最优解 min = tmp - a; ans_n = top; ans_d = bottom; } bottom++; // 分数大于等于a时增大分母 } } cout << ans_n << " " << ans_d << endl; return 0; }
总结
该算法通过贪心调整分子和分母,在时间内找到近似分数,逻辑简单且高效。尽管理论上最优有理逼近需使用连分数展开(如渐进分数),但此方法在实际应用中对多数情况有效,尤其适用于编程竞赛中的快速求解。
- 1
信息
- ID
- 651
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 4
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者