您的位置:首页 > 其它

codevs 2190 有理逼近 题解

2014-10-21 20:02 169 查看
题目描述 Description

对于一个素数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之间都不能再插入满足题意的有理分数。

输入描述 Input Description

输入文件的第一行为P、N

输出描述 Output Description

输出文件只有一行,格式为“X/Y U/V”。注意,答案必须是既约的,也就是说分子、分母的最大公约数必须等于1。

样例输入 Sample Input

样例1:

2 5

样例2:

5 100

样例输出 Sample Output

样例1:

4/3 3/2
样例2:

38/17 85/38

数据范围及提示 Data Size & Hint

P、N<30000

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

说实话,这道题真的把我唬住了……

刚看到这道题,感觉明显的二分,可是如何分?怎么分?是一个问题。

于是我想我没可以枚举分子和分母,然后找最接近的,然而 P、N<30000这的把我唬住了…

…尽管我看见了gcd(分子,分母)=1这个提示,但是我还是没有去写它(事实证明,这题很水,暴力可以a)

在时间竟破的情况下,我选择了放弃……

中午评测完以后,我发现,我们可以枚举固定区间内的分子,因为分母是从2-n的,那些远大于 分母*(p)^(1/2)的分子

是没有必要去枚举的。所以我们可以取(p)^(1/2)的上界和下界(即上下取整)这样我们可以把每一个分母的分子限制

在一个很小的区间内,再加上gcd(分子,分母)=1,还有二分枚举答案,这题就可以过了。

由于本人不会写二分,所以,我开了一个大根堆,一个小根堆来维护。看来,今晚还要补习一下二分了!!

注意:有可能输出如1/1或者2/1的情况!!

+++++++++++++++++++++代码如下++++++++++++++++++++++++++++++++++++

<span style="font-family:Comic Sans MS;font-size:18px;">#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
using namespace std;
struct node1{
int son,mot;double w;
bool operator < (const node1 &a) const
{
return w<a.w;
}
}a[3001000];
int n,q;
double p;
struct node2{
int son,mot;double w;
bool operator < (const node2 &a) const
{
return w>a.w;//×îСֵÓÅÏÈ
}
}b[3001000];
priority_queue<node1>q1;
priority_queue<node2>q2;

int gcd(int x,int y)
{
return y?gcd(y,x%y):x;
}

int main()
{
cin>>q>>n;p=sqrt(q);
int l=floor(sqrt(q)),r=ceil(sqrt(q));
for(int k=1,kk=1,i=2;i<=n;i++)
for(int j=i*l;j<=min(n,i*r);j++)
if(gcd(i,j)==1)
{
double jj,ii,z;
jj=(double)j;
ii=(double)i;
z=jj/ii;//cout<<<<endl;
if(z<p)
{
a[k].son=j;
a[k].mot=i;
a[k].w=z;
q1.push(a[k]);k++;
}
if(z>p)
{
b[kk].son=j;
b[kk].mot=i;
b[kk].w=z;
q2.push(b[kk]);kk++;
}

}
if(!q1.empty())
cout<<q1.top().son<<"/"<<q1.top().mot<<" ";
else cout<<l<<"/"<<1<<" ";

if(!q2.empty())
cout<<q2.top().son<<"/"<<q2.top().mot;
else cout<<r<<"/"<<1;

return 0;
}</span>


题目描述 Description

对于一个素数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之间都不能再插入满足题意的有理分数。

输入描述 Input Description

输入文件的第一行为P、N

输出描述 Output Description

输出文件只有一行,格式为“X/Y U/V”。注意,答案必须是既约的,也就是说分子、分母的最大公约数必须等于1。

样例输入 Sample Input

样例1:

2 5

样例2:

5 100

样例输出 Sample Output

样例1:

4/3 3/2
样例2:

38/17 85/38

数据范围及提示 Data Size & Hint

P、N<30000
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: