这道题难住我们的是小数位数,然而。。。小数位数好像不需要考虑,可是题目给出的小数部分由20位啊,double不是15还是16位吗,不会有误差吗,有知道的大神求告知。百度题解时看到了法里数列这个字眼,然后就只去百度了法里数列
百度百科:
法里数列是以英国地质学家老约翰·法里得名,他关于这数列的信刊登在1816年的《哲学杂志》。法里猜测这数列的每一项都是相邻两项的中间分数;不过,以所知道的资料,他没有证明这个性质。法里的信给柯西读了,就给了一个证明在他的《数学习题》,把这结果归到法里上。其实,另一位数学家 C. Haros 曾在1802年发表了相类似的结果,几乎可以肯定法里和柯西都没看过。所以,法里的名字给了这个数列,是历史的一次意外。
我觉得最重要的一句话,红色标出了,就是这个意思
0/1 1/1
0/1 1/2 1/1
0/1 1/3 2/3 1/1..
中间产生的分数的分母是前一项与后一项的分母之和,同理分子是前一项与后一项的分子之和。
然后这道题用二分法,最后比一下两个分数的小数部分那个更接近题目所给的那个小数
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <cstring>
#include <sstream>
#include <cmath>
#include <stack>
#include <map>
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define mod 1000000007;
using namespace std;
int main()
{
int t,k,m;
double p;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%lf",&k,&m,&p);
int x1 = 0,y1 = 1,x3 = 1,y3 = 1;
while(1)
{
int x2 = x1 + x3,y2 = y1 + y3;
if(y2 > m) break;
if(x2 * 1.0 / y2 <= p)
{
x1 = x2;
y1 = y2;
}
else
{
x3 = x2;
y3 = y2;
}
}
printf("%d ",k);
if(fabs(x1 * 1.0 / y1 - p) > fabs(x3 * 1.0 / y3 - p))
printf("%d/%d\n",x3,y3);
else printf("%d/%d\n",x1,y1);
}
return 0;
}