C++ 有理逼近

题目:有理逼近

问题描述:在这里插入图片描述

输入输出格式

输入格式:

输入文件的第一行为P、N,其中 P、N<30000。

输出格式:

输出文件只有一行,格式为“X/Y U/V”,注意:X/Y与U/V之间有一个空格,答案必须是既约的,也就是说分子、分母的最大公约数必须等于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.csdn.net/DUXS11/article/details/132045467

猜你喜欢

转载自blog.csdn.net/m0_61360607/article/details/132063565
今日推荐