$\newcommand{\O}{\mathrm{O}}$

"有理数→連分数展開", "連分数展開→有理数" の変換および $2$ つの有理数 $p, q (p < q)$ が与えられたときに $p$ と $q$ の真に間に存在する有理数 $r$ で (分子) + (分母) が最も小さいものを返す(ここで有理数と言ったとき(非負の)有理数を指すこととする).
(関数)
rtocf$(val, res)$: 有理数 $val$ を 連分数展開形 $res$ に変換する(2種類ある).
cftor$(val)$: 連分数展開形 $val$ を有理数に変換し, それを返す.
find_rational$(val1, val2)$: $2$ つの有理数 $val1, val2 (val1 < val2)$ が与えられたときに $val1$ と $val2$ の真に間に存在する有理数で (分子) + (分母) が最も小さいものを返す.
このとき (分子) + (分母) が最小のものは一意に定まることに注意する.
時間計算量: 各操作 $\O (\log A)$ ($A = \max(分子, 分母)$ とする.)
template<typename T> class Rational {
private:
static Rational make(const T& x, const T& y){
Rational m; return m.num = x, m.den = y, m;
}
public:
friend ostream& operator<<(ostream& os, const Rational& rn) {
return (os << rn.num << " / " << rn.den);
}
Rational& operator=(T val){ return *this = Rational(val); }
bool operator<(const Rational& val) const { return num*val.den < den*val.num; }
bool operator<(const T val) const { return *this < Rational(val); }
friend bool operator<(const T val1, const Rational& val2){ return Rational(val1) < val2; }
bool operator>(const Rational& val) const { return val < *this; }
bool operator>(const T val) const { return *this > Rational(val); }
friend bool operator>(const T val1, const Rational& val2){ return Rational(val1) > val2; }
bool operator<=(const Rational& val) const { return !(*this > val); }
bool operator<=(const T val) const { return *this <= Rational(val); }
friend bool operator<=(const T val1, const Rational& val2){ return Rational(val1) <= val2; }
bool operator>=(const Rational& val) const { return !(*this < val); }
bool operator>=(const T val) const { return *this >= Rational(val); }
friend bool operator>=(const T val1, const Rational& val2){ return Rational(val1) >= val2; }
bool operator==(const Rational& val) const { return num*val.den == den*val.num; }
bool operator==(const T val) const { return *this == Rational(val); }
friend bool operator==(const T val1, const Rational& val2){ return Rational(val1) == val2; }
bool operator!=(const Rational& val) const { return !(*this == val); }
bool operator!=(const T val) const { return *this != Rational(val); }
friend bool operator!=(const T val1, const Rational& val2){ return Rational(val1) != val2; }
explicit operator bool() const noexcept { return num; }
bool operator!() const noexcept { return !static_cast<bool>(*this); }
Rational operator+() const { return *this; }
Rational operator-() const { return make(-num, den); }
friend Rational abs(const Rational& val){ return make(abs(val.num), val.den); }
Rational operator+(const Rational& val) const { return make(num*val.den+val.num*den, den*val.den); }
Rational operator+(T val) const { return *this + Rational(val); }
friend Rational operator+(T a, const Rational& b){ return b + a; }
Rational& operator+=(const Rational& val){ return *this = *this + val; }
Rational& operator+=(const T& val){ return *this = *this + val; }
Rational& operator++(){ return *this += 1; }
Rational operator++(int){ return make(num + den, den); }
Rational operator-(const Rational& val) const { return make(num*val.den-val.num*den, den*val.den); }
Rational operator-(T val) const { return *this - Rational(val); }
friend Rational operator-(T a, const Rational& b){ return Rational(a) - b; }
Rational& operator-=(const Rational& val){ return *this = *this - val; }
Rational& operator-=(const T& val){ return *this = *this - val; }
Rational& operator--(){ return *this -= 1; }
Rational operator--(int){ return make(num - den, den); }
Rational operator*(const Rational& val) const { return make(num*val.num, den*val.den); }
Rational operator*(T val) const { return *this * Rational(val); }
friend Rational operator*(T a, const Rational& b){ return b * a; }
Rational& operator*=(const Rational& val){ return *this = *this * val;}
Rational& operator*=(const T& val){ return *this = *this * val; }
Rational operator/(const Rational& val) const { return make(num*val.den, den*val.num); }
Rational operator/(T val) const { return *this / Rational(val); }
friend Rational operator/(T a, const Rational& b){ return Rational(a) / b; }
Rational& operator/=(const Rational& val){ return *this / val; }
Rational& operator/=(const T& val){ return *this = *this / val; }
T num, den;
Rational(){}
Rational(T num_) : num(num_), den(1){}
Rational(T num_, T den_) : num(num_), den(den_){ if(den < 0) num = -num, den = -den; }
};
template<typename T>
bool is_valid(const Rational<T>& a, const Rational<T>& b, const Rational<T>& c)
{
return (a < b && b < c);
}
template<typename T>
void rtocf(const Rational<T>& val, vector<vector<T> >& res)
{
if(res.empty()) res.push_back(vector<T>());
res[0].push_back(val.num / val.den);
long long mod = val.num % val.den;
if(mod == 0){
res.push_back(res[0]);
if(res[0].back() == 1 && (int)res[0].size() > 1){
res[1].pop_back(), --res[1].back();
}else{
--res[0].back(), res[0].push_back(1);
}
return;
}else{
rtocf(Rational<T>(val.den, val.num-res[0].back()*val.den) , res);
}
}
template<typename T>
Rational<T> cftor(vector<T> val)
{
T a = 1, b = 0;
while(!val.empty()){
swap(a, b);
a += val.back()*b;
val.pop_back();
}
return Rational<T>(a, b);
}
template<typename T>
Rational<T> find_rational(const Rational<T> val1, const Rational<T> val2)
{
vector<vector<T> > l, r;
rtocf(val1, l), rtocf(val2, r);
vector<T> res;
for(vector<T>& lvec : l){
for(vector<T>& rvec : r){
vector<T> nw;
int i = 0, mn_size = min((int)lvec.size(), (int)rvec.size());
for(i = 0; i < mn_size; ++i){
if(lvec[i] != rvec[i]){
nw.push_back(min(lvec[i], rvec[i]) + 1);
break;
}else{
nw.push_back(lvec[i]);
}
}
if(i == mn_size){
if((int)lvec.size() > mn_size){
nw.push_back(lvec[mn_size]+1);
}else{
nw.push_back(rvec[mn_size]+1);
}
}
Rational<T> cand = cftor(nw);
if(is_valid(val1, cand, val2)) return cand;
}
}
return Rational<T>();
}
GCJ : New Elements: Part 2