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;
}

浙公网安备 33010602011771号