DestinHistoire

 

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编辑  收藏  举报

导航