題意描述
給定一個浮點數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;
}