描述

对于一个素数P,我们可以用一系列有理分数(分子、分母都是不大于N的自然数)来逼近sqrt(p),例如P=2,N=5的时候:1/1<5/4<4/3<sqrt(2)<3/2<5/3<2/1。
任 务 :
给定P、N(N>sqrt(p)),求X、Y、U、V,使x/y<sqrt(p)<u/v且x/y与sqrt(p)之间、sqrt(p)与u/v之间都不能再插入满足题意的有理分数。

 

这道题目没有数据规模的描述的话,可以依次枚举i和j使得i/j最逼近sqrt(p),但是,对于大规模的数据来说,这样无疑会超时的(TLE十分严重)。

对于i/j约等于sqrt(p)来书可以转换成 j 约等于i/sqrt(p),这样的优化,只需要一层循环的枚举就可以了,需去到大于sqrt(p)的最小值和小于sqrt(p)的最大值,不断更新最小值就可以了。

这道题的精度问题还十分重要。

#include<cstdio>
#include<cmath>
int n,p,xi,xj;
double min;
int main()
{
    scanf("%d %d\n",&p,&n);
    min=10000000.0;
    for (int i=n;i>0;i--)
    for (int j=(int)((double)i/sqrt(p))-3;j<=(int)((double)i/sqrt(p))+3;j++)
    if (i!=j)
    {
        if (j<=0||j>n)continue;
        if (sqrt(p)-(double)i/j>0&&sqrt(p)-(double)i/j-1e-7<=min)
        {
            xi=i;xj=j;
            min=sqrt(p)-((double)i/j);
        }
    }
    printf("%d/%d ",xi,xj);
    min=10000000.0;
    for (int i=n;i>0;i--)
    for (int j=(int)((double)i/sqrt(p))-3;j<=(int)((double)i/sqrt(p))+3;j++)
    if (i!=j)
    {
        if (j<=0||j>n)continue;
        if (sqrt(p)-(double)i/j<0&&(double)i/j-sqrt(p)-1e-7<=min)
        {
            xi=i;xj=j;
            min=((double)i/j)-sqrt(p);
        }
    }
    printf("%d/%d\n",xi,xj);
    return 0;
}