CF281B题解

Preface

这是一道小学数学题。

Description

要你求出一个分式 $ \frac{a}{b} $ ,使得其与 $ \frac{x}{y} $ 最接近,同时满足的情况下取 $ b $ 最小,再满足取 $ a $ 最小,同时 $ 1<=b<=n;0<=a $ 。

Method

通过小学数学可知,两个数的接近程度由他们差的绝对值的大小决定,所以我们将两个分式相减。

$ \frac{x}{y}-\frac{a}{b} $ \(=\) \(\frac{b*x-a*y}{b*y}\),然后我们就可以知道,对于分母相同的两个分式,他与\(\frac{x}{y}\)的差能最小最多只有两个数能满足,一个是差是负数的满足,一个是差是正数的满足,所以我们可以考虑二分枚举两种情况的最小值,在做一个比较,就可以得出当分母为\(b\)时分子的最优取值,然后求出了每一个合法分母所能达到的最优解之后,我们只要用刚才差的方法去选出接近程度最大的即可,当然这里有一个小优化,我们从前往后枚举分母,这样就不用判断接近程度相同得分式了,因为后面的分母比前面的大。

Code

#include<bits/stdc++.h>
using namespace std;
long long ans1,ans2,z,dom,x,y,n,dominator,molecule,l,r,mid,mol,xx1,yy1,xx2,yy2,xx,yy,i;
long long gcd(long long x,long long y)
{
	if (y==0) return x;
	long long ans=gcd(y,x % y);return ans;
}
int main()
{
	cin>>x>>y>>n;
	dominator=1;molecule=1000000;
	for (i=1;i<=n;i++)
	     {
	     	dom=i*y;
	     	l=1;r=10000000000;mol=0;
	     	while (l<=r)
	     	     {
	     	     	mid=(l+r)/2;
	     	     	if (i*x-mid*y>=0)
	     	     	    {
	     	     	    	mol=mid;l=mid+1;
						  }
					else r=mid-1;
				  }
			xx1=i*x-mol*y;yy1=mol;
		    l=1;r=10000000000;mol=0;
	     	while (l<=r)
	     	     {
	     	     	mid=(l+r)/2;
	     	     	if (i*x-mid*y<0)
	     	     	    {
	     	     	    	mol=mid;r=mid-1;
						  }
					else l=mid+1;
			      }
			xx2=-(i*x-mol*y);yy2=mol;
			if (xx1>xx2)
			     {
			     	xx1=xx2;
			     	xx=i;yy=yy2;
				 }
			else 
			        {
			        	xx=i;yy=yy1;
					}
			z=molecule*dom-dominator*xx1;
			if (z>0)
			    {
			    	ans1=yy;ans2=i;
			    	dominator=dom;molecule=xx1;
				}
		 }
	if (ans1==0) cout<<ans1<<"/"<<ans2<<endl;
	else
	    {
	    	z=gcd(ans1,ans2);ans1/=z;ans2/=z;
	    	cout<<ans1<<"/"<<ans2<<endl;
		}
	return 0;
}
posted @ 2021-04-25 18:47  OIer_Albedo  阅读(61)  评论(0)    收藏  举报