题意是给你个 a / b a/b a/b,让你找最接近 a / b a/b a/b的 c / d c/d c/d且满足 c < d < b c<d<b c<d<b
连分数
对于任一一个数,都可以表示为
(
a
0
,
a
1
,
a
2
⋯
a
n
)
(a_0,a_1,a_2\cdots a_n)
(a0,a1,a2⋯an)
意思是
n
=
a
0
+
1
a
1
+
1
a
2
+
1
a
3
+
⋯
n=a_0+\frac{1}{a_1+\frac{1}{a_2+\frac{1}{a_3+\cdots}}}
n=a0+a1+a2+a3+⋯111
如
2
3
=
0
+
1
1
+
1
2
\frac{2}{3}=0+\frac{1}{1+\frac{1}{2}}
32=0+1+211
所以
2
3
=
(
0
,
1
,
2
)
\frac{2}{3}=(0,1,2)
32=(0,1,2)
有理数的连分数n是有限的,无理数是无限的。
这里只讨论有理数,即可分数表示的数
A
B
=
a
0
+
1
a
1
+
1
a
2
+
1
a
3
+
⋯
\frac{A}{B}=a_0+\frac{1}{a_1+\frac{1}{a_2+\frac{1}{a_3+\cdots}}}
BA=a0+a1+a2+a3+⋯111
性质一
[ 0 , a 0 , a 1 , a 2 , a 3 ⋯ a n ] 和 [ a 0 , a 1 , a 2 ⋯ a n ] [0,a_0,a_1,a_2,a_3\cdots a_n]和[a_0,a_1,a_2\cdots a_n] [0,a0,a1,a2,a3⋯an]和[a0,a1,a2⋯an]互为倒数
性质二
若对于最简分数(非整数) [ a 0 , a 1 , a 2 ⋯ a n ] 与 [ a 0 , a 1 , a 2 ⋯ a n + 1 ] [a_0,a_1,a_2\cdots a_n]与[a_0,a_1,a_2\cdots a_n+1] [a0,a1,a2⋯an]与[a0,a1,a2⋯an+1]最接近,但相差不等于0,且后者分母比前者大 。
还有很多性质,以后遇到再说。
其他以后接触
回到本题,显然性质二不满足题意,所以
a
n
+
1
a_n+1
an+1要变成
a
n
−
1
a_n-1
an−1
没有严格的证明,简单说一下自己的理解
这题
a
<
b
a<b
a<b,所以
a
0
=
0
a_0=0
a0=0,所以
[
a
1
,
a
2
,
⋯
a
n
]
=
(
(
a
n
−
1
+
a
n
−
1
)
−
1
‘
+
a
n
−
2
)
−
1
+
a
n
−
3
)
−
1
+
⋯
+
a
1
)
−
1
[a_1,a_2,\cdots a_n]=((a_ n^{-1}+a_{n-1})^{-1`}+a_{n-2})^{-1}+a_{n-3})^{-1}+\cdots+a_1)^{-1}
[a1,a2,⋯an]=((an−1+an−1)−1‘+an−2)−1+an−3)−1+⋯+a1)−1
显然改变
a
n
a_n
an的值对整体的值改变的影响最慢,所以变化最小的会产生在
a
n
+
1
a_n+1
an+1或
a
n
−
1
a_n-1
an−1上
至于
a
n
+
1
a_n+1
an+1为什么会导致分母变大呢,即
d
>
b
d>b
d>b
列出几项就知道了
[
a
1
,
a
2
]
[a_1,a_2]
[a1,a2]即
1
a
1
+
1
a
2
\frac{1}{a_1+\frac{1}{a_2}}
a1+a211 的分母为
a
1
a
2
+
1
a_1a_2+1
a1a2+1
[
a
1
,
a
2
,
a
3
]
[a_1,a_2,a_3]
[a1,a2,a3]的分母为
a
1
a
2
a
3
+
a
1
+
a
2
a_1a_2a_3+a_1+a_2
a1a2a3+a1+a2
⋯
\cdots
⋯
可知变大任意一个
a
a
a分母都会变大
所以本题可以先把数化为连分数,
a
n
−
1
a_n-1
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;
}
}