BZOJ-2712 [Violet 2]棒球(类欧几里得算法)
题目描述
给出一个四舍五入到 \(n(1\leq n\leq 15)\) 位小数的数字 \(r(0\leq r<1)\),构造四舍五入后等于 \(r\) 的分数 \(\frac{p}{q}\),使 \(q\) 最小,输出 \(q\)。
分析
可以发现此分数的取值范围是:\(\frac{10r-5}{10^{n+1}}<\frac{p}{q}<\frac{10r+5}{10^{n+1}}\)。
令 \(a=10r-5,b=10^{n+1},c=10r+5,d=10^{n+1}\)。分以下几种情况讨论:
\(1.\) \(\frac{a}{b}\) 和 \(\frac{c}{d}\) 之间存在某个整数,即 \(\lfloor\frac{a}{b}\rfloor+1\leq \lceil\frac{c}{d}\rceil-1\),此时取 \(q=1,p=\lfloor\frac{a}{b}\rfloor+1\)。
\(2.\) \(a=0\),式子变成 \(\frac{p}{q}<\frac{c}{d}\),即 \(\frac{pd}{c}<q\),此时取 \(p=1,q=\lfloor\frac{d}{c}\rfloor+1\)。
\(3.\) \(a<b\) 且 \(c\leq d\),把不等式调整为分子大于分母的形式,即 \(\frac{d}{c}<\frac{q}{p}<\frac{b}{a}\),可以递归处理。
\(4.\) \(a\geq b\),\(\frac{a}{b}-\lfloor\frac{a}{b}\rfloor=\frac{a\%b}{b}<\frac{p}{q}-\lfloor\frac{a}{b}\rfloor<\frac{c}{d}-\lfloor\frac{a}{b}\rfloor=\frac{c-d\lfloor\frac{a}{b}\rfloor}{d}\),类欧几里得算法递归处理。
答案为 \(\min(b,q)\)。
代码
#include<bits/stdc++.h>
using namespace std;
int n;
long long a,b,c,d,p,q;
void solve(long long a,long long b,long long c,long long d,long long &p,long long &q)
{
if(a/b+1<=(c+d-1)/d-1)
p=a/b+1,q=1;
else if(a==0)
p=1,q=d/c+1;
else if(a<b&&c<=d)
solve(d,c,b,a,q,p);
else
{
solve(a%b,b,c-d*(a/b),d,p,q);
p=p+q*(a/b);
}
}
int main()
{
long long r;
while(~scanf("%d 0.%lld",&n,&r))
{
if(r==0)
{
puts("1");
continue;
}
long long fm=10;
while(n--)
fm=fm*10ll;
a=r*10-5;
b=fm;
c=r*10+5;
d=fm;
long long gcd=__gcd(a,b);
a=a/gcd,b=b/gcd;
gcd=__gcd(c,d);
c=c/gcd,d=d/gcd;
//cout<<a<<" "<<b<<" "<<c<<" "<<d<<endl;
solve(a,b,c,d,p,q);
printf("%lld\n",min(b,q));
}
return 0;
}
posted on 2020-12-01 14:11 DestinHistoire 阅读(81) 评论(0) 编辑 收藏 举报