题意:
分析:
- 前置芝士:类欧几里得算法
其实类欧,除了复杂度证明和欧几里得差不多,其他半毛钱关系都没有,类欧是一种合并降低复杂度的方法
首先小数化分数,上界是小数部分 ( imes 10+14) 下界是小数部分 ( imes 10-5)
(frac{a}{b}le frac{p}{q}le frac{c}{d})
分类讨论:
- (a=0) 时 (frac{p}{q}le frac{c}{d} o qge frac{dp}{c}), 即 (min_q=lfloorfrac{d}{c} floor+1)
- (age b) 时 把整数部分消掉 (frac{amod b}{b}le frac{p-frac{a}{b}*q}{q}le frac{c-frac{a}{b}*d}{d}),这样递归下去边界就是 (a==0)
- (a<b) 时 通过翻转一下,转化成第二种情况以倒数继续递归 (frac{b}{a}ge frac{p}{q}ge frac{d}{c})
代码:
#include<bits/stdc++.h>
#define pii pair<int,int>
#define mk(x,y) make_pair(x,y)
#define lc rt<<1
#define rc rt<<1|1
#define pb push_back
#define fir first
#define sec second
#define inl inline
#define reg register
using namespace std;
namespace zzc
{
typedef long long ll;
inline ll read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
ll n,r;
void solve(ll a,ll b,ll c,ll d,ll &p,ll &q)
{
if((a/b+1)<=((c-1)/d)) p=(a/b)+1,q=1;
else if(!a) p=1,q=(d/c)+1;
else if(a<b) solve(d,c,b,a,q,p);
else
{
solve(a%b,b,c-(a/b)*d,d,p,q);
p+=q*(a/b);
}
}
void work()
{
ll a,b,c,d,p,q,x,g;
while (scanf("%lld 0.%lld",&n,&r)==2)
{
if (r==0) {puts("1");continue;}
x=10;while(n--)x*=10;
a=r*10-5;b=x;
c=r*10+5;d=x;
g=__gcd(a,b);a/=g;b/=g;
g=__gcd(c,d);c/=g;d/=g;
solve(a,b,c,d,p,q);
printf("%lld
",min(q,b));
}
}
}
int main()
{
zzc::work();
return 0;
}