From 1bb97452999acf4916742cd403f1e03adbf92701 Mon Sep 17 00:00:00 2001 From: Matej Focko Date: Sat, 12 Aug 2023 23:19:59 +0200 Subject: [PATCH] chore(cpp): factor out modular integer to a struct Signed-off-by: Matej Focko --- .common/cpp/skeleton.cpp | 51 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/.common/cpp/skeleton.cpp b/.common/cpp/skeleton.cpp index 5f057a1..a8686dd 100644 --- a/.common/cpp/skeleton.cpp +++ b/.common/cpp/skeleton.cpp @@ -151,14 +151,61 @@ Container collect(std::size_t size) { #pragma endregion /* input */ #pragma region math -static constexpr std::int32_t MODULO = 1000000007; - long pow(long base, long exp) { if (exp == 0) return 1; long half = pow(base, exp / 2); if (exp % 2 == 0) return half * half; return half * half * base; } + +template +struct Z { + Z(std::int64_t x = 0) : x(x % MODULO) {} + + Z pow(std::uint32_t exp) const { + auto ans = 1; + auto base = x; + + for (; exp > 0; exp >>= 1) { + if (exp % 2 == 1) { + ans *= base; + } + + base *= base; + } + + return ans; + } + + Z inv() const { + assert(x != 0); + return pow(MODULO - 2); + } + + Z operator-() const { return {-x}; } + Z operator+=(const Z &rhs) { x = (x + rhs.x) % MODULO; } + Z operator-=(const Z &rhs) { x = (x - rhs.x) % MODULO; } + Z operator*=(const Z &rhs) { x = (x * rhs.x) % MODULO; } + Z operator/=(const Z &rhs) { x = (x * rhs.inv().x) % MODULO; } + + friend Z operator+(Z lhs, const Z &rhs) { return lhs += rhs; } + friend Z operator-(Z lhs, const Z &rhs) { return lhs -= rhs; } + friend Z operator*(Z lhs, const Z &rhs) { return lhs *= rhs; } + friend Z operator/(Z lhs, const Z &rhs) { return lhs /= rhs; } + + friend std::istream &operator>>(std::istream &is, Z &z) { + is >> z.x; + z.x %= MODULO; + return is; + } + + friend std::ostream &operator<<(std::ostream &os, const Z &z) { + return os << z.x; + } + + private: + std::int64_t x; +}; #pragma endregion /* math */ #pragma region output