struct Frac {
long long n, d;
Frac(long long n = 0, long long d = 1) : n(n), d(d) {
assert(d != 0);
}
void reduct() {
long long k = __gcd(llabs(n), d);
n /= k;
d /= k;
}
friend Frac operator+(const Frac &x, const Frac &y) {
Frac res(x.n * y.d + y.n * x.d, x.d * y.d);
res.reduct();
return res;
}
friend Frac operator-(const Frac &x, const Frac &y) {
Frac res(x.n * y.d - y.n * x.d, x.d * y.d);
res.reduct();
return res;
}
friend Frac operator*(const Frac &x, const Frac &y) {
Frac res(x.n * y.n, x.d * y.d);
res.reduct();
return res;
}
Frac operator/(const Frac &_) {
return *this * _.rev();
}
Frac& operator+=(const Frac &_) {
*this = *this + _;
return *this;
}
Frac& operator-=(const Frac &_) {
*this = *this - _;
return *this;
}
Frac& operator*=(const Frac &_) {
*this = *this * _;
return *this;
}
Frac& operator/=(const Frac &_) {
*this = *this / _;
return *this;
}
Frac rev() const {
Frac res(d, llabs(n));
if (n < 0) {
res.n = -res.n;
}
return res;
}
friend ostream& operator<<(ostream &os, const Frac &x) {
os << x.n
if (x.d !== 1) os << "/" << x.n;
return os;
}
}; // Frac