题意描述
给定一个浮点数A和一个整数L,求在范围[1,L]内的两个整数n和d,使得n和d能近似等于A,且使误差|A-n/d|最小。
输入格式
一行两个数:浮点数A,整数L。数据保证有解。
输出格式
一行两个整数n和d
输入样例
3.14159265358979 10000
输出样例
355 113
思路:
所谓“追赶法”,顾名思义,正如两个人“赛跑”,甲超过乙之后乙不服,要超过甲,甲被超过之后又超过乙,以此轮换。而两个数的“追赶”则是保持一定比例,使a/b在k左右“徘徊”。如果a/b>k,说明分子太大或者分母太小,对分子减小,或者使分母增大。如果a/b<k则反之。
本题中,A分为两种情况:A>=1,0<A<1.对于前一种情况,n>=d,后一种情况n<d。假定d为1,如果后一种情况n将<1,不利于处理。故判断A情况,若为第二种,A = 1/A并将其记录。
然后,初始d为1,n为A*d,然后不断判断n/d和A的大小,如果前者比后者大,说明d太小,d++,否则n++。定义变量保存最优解。
代码:
#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
int main(){
double A;
int L;
bool flag = true;
scanf("%lf %d",&A,&L);
if(A < 1){
A = 1/A;
flag = false;
}
int l = 1,r = (int)A,res_l = l,res_r = r;
double now = (double)INF;
while(l <= r && r <= L){
double tmp = (double)r/l;
if(abs(tmp - A) < now){//为更优解
res_l = l;
res_r = r;
now = abs(tmp - A);
}
if(tmp < A)r++;
else l++;
}
if(flag)printf("%d %d",res_r,res_l);
else printf("%d %d",res_l,res_r);//如果A < 1交换结果输出顺序
return 0;
}