#include #include using namespace std; /** * A generic function for computing the GCD * @tparam R : this template variable should be a type for which all the necessary * operations for Euclidean domains have been implemented * @param a * @param b * @return */ template R gcd(R a, R b) { if (b == 0) return a; R r = a % b; while (r != 0) { a = b; b = r; r = a % b; } return b; } /** * Rational on R which is always normalized. * @tparam R : a type for Euclidean domain */ template struct ratio { R num; R denom; }; template ratio &rational_of(R n) { return ratio(n, 1); } template ratio &normalize(ratio &n) { const R gcd = gcd(n.num, n.denom); n.num = n.num / gcd; n.denom = n.denom / gcd; return n; } template ratio &operator+(const ratio &l, const ratio &r) { return normalize(rational(l.num * r.denom + r.num * l.denom, l.denom * r.denom)); } template ratio &operator-(const ratio &l, const ratio &r) { return normalize(rational(l.num * r.denom - r.num * l.denom, l.denom * r.denom)); } template ratio &operator*(const ratio &l, const ratio &r) { return normalize(rational(l.num * r.num, l.denom * r.denom)); } template ratio &operator/(const ratio &l, const ratio &r) { return normalize(rational(l.num * r.denom, r.denom * l.num)); } template bool operator==(const ratio &l, const ratio &r) { return l.num == r.num && l.denom == r.denom; } template bool operator!=(const ratio &l, const ratio &r) { return l.num != r.num || l.denom != r.denom; } template std::ostream& operator<<(std::ostream& os, const ratio& r) { os << r.a << "/" << r.b; return os; } /** * Prime field where number is kept to be in range [0, p). */ template struct prime_field { size_t number; }; template prime_field

&operator+(const prime_field

&l, const prime_field

&r) { return prime_field((l.number + r.number) % p); } template prime_field

&operator-(const prime_field

&l, const prime_field

&r) { return prime_field((l.number - r.number) % p); } template prime_field

&operator*(const prime_field

&l, const prime_field

&r) { return prime_field((l.number * r.number) % p); } // TODO prime_field / template bool operator==(const prime_field

&l, const prime_field

&r) { return l.number == r.number; } template bool operator!=(const prime_field

&l, const prime_field

&r) { return l.number != r.number; }