题目:有理逼近
问题描述:
输入输出格式
输入格式:
输入文件的第一行为 P 、 N P、N P、N,其中 P 、 N < 30000 P、N<30000 P、N<30000。
输出格式:
输出文件只有一行,格式为“ X / Y U / V X/Y U/V X/YU/V”,注意: X / Y X/Y X/Y与 U / V U/V U/V之间有一个空格,答案必须是既约的,也就是说分子、分母的最大公约数必须等于 1 1 1。
输入输出样例
输入样例#1:
5 100
输出样例#1:
38/17 85/38
做题思路:
这题我用的是枚举,就是从1~m中枚举出比根号P大的最小的一个分数与比根号P小的最大的一个分数。
好了好了,直接看代码注释吧:
AC代码
#include<bits/stdc++.h>
using namespace std;
long double t,ma=-1,mi=0x7fffffff;//ma是比根号P小的最大的一个分数值,mi是比根号P大的最小的一个分
数值
//注意:mi在数据较大的数据时初值要设的大一些,作者就在这里卡了好久
int x,y,u,v,p,m,fm;
int main()
{
cin>>p>>m;
t=sqrt(p);//由题目要求根号P
for(fm=1;fm<=m;fm++){//这个循环是枚举分母(fm)的
int fz=int(t*fm);//这个是分子(fz)
//赋值int(t*fm)这个东西是因为:分数值要最接近结果(t)所以 fz(分子)/fm(分母)=t
//然后移项就可以得出 fz=int(t*fm)。
if(fz>m) break;//如果分子超出题目范围就直接break
if(fz*1.0/fm>ma){//这里求比根号P小的最大的一个分数值
ma=fz*1.0/fm;//记录
x=fz;//x,y以及后面的u,v是记录最终结果的
y=fm;
}
if (fz>=m)//如果分子超出题目范围就直接break(同上)
break;
if((fz+1)*1.0/fm<mi){//这里求比根号P大的最小的一个分数值
mi=(fz+1)*1.0/fm;
u=fz+1;
v=fm;
}
}
cout<<x<<"/"<<y<<" "<<u<<"/"<<v;//最后输出就好啦
return 0;
}
总结:
这题其实不难,而且还有很多其他的方法,主要是得要有思路!!!
如果大家没听懂可以看看这篇文章,我就是看这篇文章学会的:
https://blog.youkuaiyun.com/DUXS11/article/details/132045467