P1298 最接近的分数
2026-06-12 20:31:50
发布于:江西
P1298 最接近的分数
题目描述
给出一个正小数,找出分子(分子 )不超过 ,分母不超过 的最简分数或整数,使其最接近给出的小数。“最接近”是指在数轴上该分数距离给出的小数最近,如果这个分数不唯一,输出 TOO MANY。
输入格式
输入共有 行,第一行包含两个用空格隔开的正整数 和 ,表示要求的分数其分子不超过 ,分母不超过 ;第二行为小数 , 的整数部分为一个阿拉伯数字,小数部分最多有十位。
输出格式
输出仅 行,若解唯一则输出 分子/分母(整数 写成 ),否则输出 TOO MANY。
输入输出样例 #1
输入 #1
360 120
3.1415926536
输出 #1
355/113
说明/提示
数据范围及约定
对于全部数据,保证 。
AC代码
#include<bits/stdc++.h>
using namespace std;
// 辗转相除法求最大公约数
long long gcd(long long a, long long b){
while(b){
long long t=b;
b=a%b;
a=t;
}
return a;
}
// 避免浮点数精度误差
int f(double x) {
return (x>1e-12)-(x<-1e-12);
}
int main(){
long long m,n;
long double r;
cin>>m>>n>>r;
// 初始化Stern-Brocot树左右边界
long long lm=0,ln=1;
long long rm=1,rn=0;
long long mm=0,mn=0;
long double ans=0.0;
// 通过二分查找逼近目标
while(true){
// 计算中位分数
mm=lm+rm;
mn=ln+rn;
// 超过限定范围,停止逼近
if(mm>m || mn>n){
break;
}
// 判断误差
ans=(long double)mm/mn;
int flag=f(r*mn-mm);
if(flag==0){
cout<<mm<<'/'<<mn;
return 0;
}
// 更新左右边界
if(flag>0){
lm=mm;
ln=mn;
}else{
rm=mm;
rn=mn;
}
}
// 计算左右分数与r的误差
long double errl=fabs((long double)lm/ln-r);
long double errr=fabs((long double)rm/rn-r);
// 判断误差是否相等
int flag=f((r-errl)-(errr-r));
if(flag==0){
cout<<"TOO MANY";
}else if(errl<errr){
cout<<lm/gcd(lm,ln)<<"/"<<ln/gcd(lm,ln);
}else{
cout<<rm/gcd(rm,rn)<<"/"<<rn/gcd(rm,rn);
}
return 0;
}
解析
算法核心
利用树的性质二分逼近目标小数。
Stern–Brocot 树
它包含所有正的最简有理分数的二叉树。
它有以下几个性质:
- 单调性:在Stern–Brocot 树的构造中,每一层的分数都是单调递增的
- 最简性:在Stern–Brocot 树的构造中,每个分数都是最简分数
- 完全性:Stern–Brocot 树包括了所有正的最简分数
参考资料
Stern–Brocot 树与 Farey 序列
http://oi-wiki.com/math/number-theory/stern-brocot/#sternbrocot-%E6%A0%91
【算法】震惊!Stern–Brocot tree竟与辗转相除有关?
https://www.bilibili.com/video/BV1PE411W7Ze/?spm_id_from=333.1387.upload.video_card.click&vd_source=52f911b4fdd6c20738314dcaaa2c370d
【算法】什么是Stern-Brocot tree?香不香,味道还可以吗?
https://www.bilibili.com/video/BV1m7411w7bs/?spm_id_from=333.337.search-card.all.click&vd_source=52f911b4fdd6c20738314dcaaa2c370d
【算法】这个算法明明使用二分却过分暴力!继续品尝Stern–Brocot tree
https://www.bilibili.com/video/BV1x7411F7PE/?spm_id_from=333.337.search-card.all.click&vd_source=52f911b4fdd6c20738314dcaaa2c370d
【漫士】闰的哲学:连分数有理近似与黄金分割的密码
https://www.bilibili.com/video/BV1qRfKYiEfn/?spm_id_from=333.337.search-card.all.click&vd_source=52f911b4fdd6c20738314dcaaa2c370d
【漫士-无痛高数】一个游戏帮你直观理解极限和连续
https://www.bilibili.com/video/BV1QByuBWE7m/?spm_id_from=333.1387.search.video_card.click&vd_source=52f911b4fdd6c20738314dcaaa2c370d
初等数论-第十八课 什么是连分数?怎么算它的值呢?快来学习下吧
https://www.bilibili.com/video/BV1FL411c7r4/?spm_id_from=333.337.search-card.all.click&vd_source=52f911b4fdd6c20738314dcaaa2c370d
思考
Stern–Brocot 树扩展
- Farey 序列
- 连分数
- 无理数的有理逼近
- 辗转相除
推荐题目
- P1299 切孔机
- P1306 斐波那契公约数
- P1354 房间最短路问题
- CF525E Anya and Cubes
- CF1006F Xor-Paths
这里空空如也




















有帮助,赞一个