题意是给你个
a/b,让你找最接近
a/b的
c/d且满足
c<d<b
连分数
对于任一一个数,都可以表示为
(a0,a1,a2⋯an)
意思是
n=a0+a1+a2+a3+⋯111
如
32=0+1+211
所以
32=(0,1,2)
有理数的连分数n是有限的,无理数是无限的。
这里只讨论有理数,即可分数表示的数
BA=a0+a1+a2+a3+⋯111
性质一
[0,a0,a1,a2,a3⋯an]和[a0,a1,a2⋯an]互为倒数
性质二
若对于最简分数(非整数)
[a0,a1,a2⋯an]与[a0,a1,a2⋯an+1]最接近,但相差不等于0,且后者分母比前者大 。
还有很多性质,以后遇到再说。
其他以后接触
回到本题,显然性质二不满足题意,所以
an+1要变成
an−1
没有严格的证明,简单说一下自己的理解
这题
a<b,所以
a0=0,所以
[a1,a2,⋯an]=((an−1+an−1)−1‘+an−2)−1+an−3)−1+⋯+a1)−1
显然改变
an的值对整体的值改变的影响最慢,所以变化最小的会产生在
an+1或
an−1上
至于
an+1为什么会导致分母变大呢,即
d>b
列出几项就知道了
[a1,a2]即
a1+a211 的分母为
a1a2+1
[a1,a2,a3]的分母为
a1a2a3+a1+a2
⋯
可知变大任意一个
a分母都会变大
所以本题可以先把数化为连分数,
an−1后再逆回去即可
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
using namespace std;
ll A[50];
int top;
int main()
{
ios::sync_with_stdio(0),cin.tie(0);
int T;
cin>>T;
while(T--)
{
top=0;
char s;
ll a=0,b=0,C,D,c;
cin>>a>>s>>b;
ll G=__gcd(a,b);
if(G>1){
cout<<a/G<<"/"<<b/G<<endl;
continue;
}
A[++top]=b/a;
while(b%a!=0)
{
c=b%a,b=a,a=c,A[++top]=b/a;
}
A[top]--;
C=1,D=A[top];
for(int i=top-1;i>=1;i--)
{
c=C,C=D;
D=A[i]*D+c;
}
cout<<C<<"/"<<D<<endl;
}
}