题目描述
小B最近学习了
S
t
e
r
n
−
B
r
o
c
o
t
Stern-Brocot
Stern−Brocot
t
r
e
e
tree
tree这是一种能表示所有正有理数的结构,如下图
不难发现所有正有理数形成了一颗以
1
1
\frac{1}{1}
11为根的树,一个树的位置可以用字符串表示,即从根找到这个数在树上的位置,向左用L表示向右用R表示,根节点对应的字符串为空串。
现给出a,b, 求
a
b
\frac{a}{b}
ba在树中的位置
样例:
输入
10 6
输出
RLR
对于30%的数据,字符串长度≤20。
对于全部的数据a,b≤106。
刚开始我以为很难,没有理解出sbt的意思。
于是就想着暴力建树然后在树上暴力查找。
emm,对于一个节点,我们如果能维护出他左边和右边需要加上的数,我们就能建立出这个节点所表示的有理数,
这个节点的左右需要加的数取决于它是左子节点还是右子节点,同时我们还需要父亲的父亲的信息,我们可以在建立完父亲节点的时候处理完这些信息。
然后我们就可以快乐的爆搜了。
为了防止我们的搜索连30都过不去,我们考虑优化,
那么我们观察这颗树,从
1
1
\frac{1}{1}
11开始,左边的比右边小,最左边的一直递减,最右边一直递增,
那我们在观察任意一个节点,发现每个节点都满足像刚才根节点那样的性质,即左子节点比右子节点小
于是我们在找的时候可以直接判断自己要找的方向,建树也不用全建出来,直接建一条链,直通答案的那种。
但是我们再稍稍想一下会发现,一个点把信息处理好打包给下一个点时,这个点就没用了,那我们岂不是连树也不用建了?
直接搜索,维护出自己需要的信息,然后O(n)就过了这道题。
#include<bits/stdc++.h>
#define MAXN 1000010
#define N 100010
#define rg register
#define INF 0x3f3f3f3f
#define gtc() getchar()
#define ll long long
using namespace std;
template<class T>
inline void read(T &s){
T w = 1, ch = gtc(); s = 0;
while(!isdigit(ch)){if(ch == '-') w = -1; ch = gtc();}
while(isdigit(ch)){s = s * 10 + ch - '0'; ch = gtc();}
s *= w;
}
inline int gcd(int a, int b){
return a % b == 0 ? b : gcd(b, a % b);
}
int n, m;
struct node{
int son, mt;
string way;
}t[MAXN];
int xx;//nl,nm是做边需要加的分子和分母,nr,nn同理,fs,fm是当前节点的信息
//这个搜索是建树的函数直接魔改过来的(看函数名就能看出来)有一些东西是不需要的
void build(int k, int nl, int nm, int nr, int nn, int rot, string way, int fs, int fm){
if(fs == n && fm == m){
cout << way << endl;
xx = -1; return ;
}
if(rot > xx) return ;
if(fs * m > fm * n){
build(k << 1, nl, nm, fs, fm, rot + 1, way+"L", fs + nl, fm + nm);
}
else build(k << 1 | 1, fs, fm, nr, nn, rot + 1, way+"R", fs + nr, fm + nn);
}
int main()
{
freopen("sbt.in", "r", stdin);
freopen("sbt.out", "w", stdout);
read(n), read(m);
int k = n > m ? gcd(n, m) : gcd(m, n);
//n,m不互质,我们要先约分
n /= k, m /= k;
xx = n > m ? m + 1 : n + 1;
if(n == m || n == 0 || m == 0){
puts(""); return 0;
}
if(n > m){
build(1<<1|1, 1, 1, 1, 0, 1, "R", 2, 1);
}
else build(1<<1, 0, 1, 1, 1, 1, "L", 1, 2);
return 0;
}