大家都说我出题“老不正经”,好吧,我就正经一回,作者我很“正经”得告诉大家,这是一道题目,而且这道题很难。
按递增的顺序告诉你n(1<=n<=1000000)个正整数(每个正整数都小于231)和一个正实数p(0.000001<=p<=108),要求求出该数列中的比例最接近p的两个数a,b(即取两个数a,b,并且a,b可以相同,使得fabs((double)a/b - p)最小),并且用最简分数表示。比如最终答案是4/6,则输出要是2/3;比如最终答案是3/3,则输出1/1。
Input
有多组数据,每组数据有3行:第一行一个正整数n,表示给出数列中数的个数;第二行n个正整数,
并且数列递增,两个数之间用一个空格隔开;第三行一个正实数p。
Output
每组数据对应一个输出,表示要求的那个分数,a/b最简分数形式。
Sample Input
5
1 4 5 6 7
0.666
Sample Output
2/3
#include<bits/stdc++.h>
using namespace std;
const double EPS=1e-6;
const int MAXN=1000005;
int n,l,r;
long long a[MAXN],up,down;
double x;
int main()
{
while(scanf("%d",&n)!=EOF)
{
up=down=0;
for(int i=1;i<=n;++i)
{
scanf("%lld",&a[i]);
}
sort(a+1,a+1+n);
scanf("%lf",&x);
int r=1;
for(int i=1;i<=n;++i)
{
while((double)a[i]/(double)a[r]>x&&r<n)++r;
if(!down||abs(x-(double)a[i]/(double)a[r])<abs(x-(double)up/(double)down))
{
up=a[i];
down=a[r];
}
if(r>1&&(!down||abs(x-(double)a[i]/(double)a[r-1])<abs(x-(double)up/(double)down)))
{
up=a[i];
down=a[r-1];
}
}
long long g=__gcd(up,down);
up/=g;
down/=g;
printf("%lld/%lld\n",up,down);
}
return 0;
}