This documentation is automatically generated by online-judge-tools/verification-helper
View the Project on GitHub naskya/cp-library-cpp
#define PROBLEM "https://atcoder.jp/contests/abc156/tasks/abc156_d" #include <iostream> #include "../../../include/algebra/static_modint.hpp" #include "../../../include/combinatorics/factorial.hpp" int main() { int N, A, B; std::cin >> N >> A >> B; using mint = lib::static_modint<1000000007>; mint res = mint(2).pow(N) - 1; res -= lib::combination<int, mint>(N, A); res -= lib::combination<int, mint>(N, B); std::cout << res << '\n'; }
#line 1 "test/combinatorics/factorial/2.test.cpp" #define PROBLEM "https://atcoder.jp/contests/abc156/tasks/abc156_d" #include <iostream> #line 1 "include/algebra/static_modint.hpp" //! @file static_modint.hpp #ifndef CP_LIBRARY_STATIC_MODINT_HPP #define CP_LIBRARY_STATIC_MODINT_HPP #include <cassert> #include <cstdint> #line 10 "include/algebra/static_modint.hpp" #include <limits> #include <type_traits> #define CP_LIBRARY_USE_CONSTEXPR #ifndef CP_LIBRARY_WARN # if (CP_LIBRARY_DEBUG_LEVEL >= 1) //! @brief Print warning message //! @note You can suppress the warning by uncommenting the following line # define CP_LIBRARY_WARN(msg) (std::cerr << (msg) << '\n') // # define CP_LIBRARY_WARN(msg) (static_cast<void>(0)) # else # define CP_LIBRARY_WARN(msg) (static_cast<void>(0)) # undef CP_LIBRARY_USE_CONSTEXPR # define CP_LIBRARY_USE_CONSTEXPR constexpr # endif # define CP_LIBRARY_WARN_NOT_DEFINED #endif #ifndef CP_LIBRARY_ASSERT //! @brief Assert macro # define CP_LIBRARY_ASSERT(...) assert(__VA_ARGS__) # define CP_LIBRARY_ASSERT_NOT_DEFINED #endif namespace lib { //! @brief modint (for compile-time constant modulo) //! @tparam modulo modulo (e.g. 1000000007). template <std::int_least32_t modulo, std::enable_if_t<(1 < modulo) && (modulo < std::numeric_limits<std::int_least32_t>::max() / 2), std::nullptr_t> = nullptr> struct static_modint { private: std::int_least32_t value; //! @param n non-zero integer //! @return multiplicative inverse of n template <typename Tp> [[nodiscard]] static std::int_least32_t calc_inverse(Tp n) { CP_LIBRARY_ASSERT(n != 0); Tp b = modulo, u = 1, v = 0, t; while (b > 0) { t = n / b; // std::swap is not necessarily constexpr in C++17 // std::swap(n -= t * b, b); Tp tmp = std::move(n -= t * b); n = std::move(b); b = std::move(tmp); // std::swap(u -= t * v, v); tmp = std::move(u -= t * v); u = std::move(v); v = std::move(tmp); } if (u < 0) u += modulo; return static_cast<std::int_least32_t>(u); } //! @brief Calculate modulo and keep the value within [0, modulo) //! @param v integer //! @return integer within [0, modulo) //! @note Time complexity: O(1) template <typename Tp> [[nodiscard]] static constexpr std::int_least32_t clamp_ll(Tp v) noexcept { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wsign-compare" if (modulo <= v || v < -modulo) v %= modulo; #pragma GCC diagnostic pop if (v < 0) v += modulo; return static_cast<std::int_least32_t>(v); } //! @brief Calculate modulo and keep the value within [0, modulo) //! @note Time complexity: O(1) constexpr void clamp_self() noexcept { if (0 <= value) { if (value < modulo) return; if (value < modulo * 2) value -= modulo; else value -= modulo * 2; } else { if (-modulo < value) value += modulo; else if (-modulo * 2 < value) value += modulo * 2; else { value += modulo; value += modulo * 2; } } } public: //! @brief underlying integer type using type = std::int_least32_t; //! @return modulo (e.g. 1000000007) [[nodiscard]] static constexpr type mod() noexcept { return modulo; } //! @brief Create a modint of value 0 constexpr static_modint() noexcept : value(0) {} //! @brief Create a modint without taking modulo constexpr static_modint(const type v, bool) noexcept : value(v) {} //! @brief Create a modint template <typename ValueType> constexpr static_modint(const ValueType v) noexcept : value() { if constexpr (std::is_integral_v<ValueType> && (std::numeric_limits<ValueType>::digits <= 32)) { value = v; clamp_self(); } else { value = clamp_ll(v); } } [[nodiscard]] constexpr static_modint operator+(const static_modint rhs) const noexcept { return static_modint(value + rhs.value); } [[nodiscard]] constexpr static_modint operator-(const static_modint rhs) const noexcept { return static_modint(value - rhs.value); } [[nodiscard]] constexpr static_modint operator*(const static_modint rhs) const noexcept { return static_modint(static_cast<std::int_least64_t>(value) * rhs.value); } [[nodiscard]] static_modint operator/(const static_modint rhs) const { return static_modint(static_cast<std::int_least64_t>(value) * calc_inverse(rhs.value)); } [[nodiscard]] CP_LIBRARY_USE_CONSTEXPR static_modint operator%(const static_modint rhs) const { CP_LIBRARY_WARN("static_modint::operator% : Are you sure you want to do this?"); return static_modint(value % rhs.value); } [[nodiscard]] CP_LIBRARY_USE_CONSTEXPR static_modint operator&(const static_modint rhs) const { CP_LIBRARY_WARN("static_modint::operator& : Are you sure you want to do this?"); return static_modint(value & rhs.value, true); } [[nodiscard]] CP_LIBRARY_USE_CONSTEXPR static_modint operator|(const static_modint rhs) const { CP_LIBRARY_WARN("static_modint::operator| : Are you sure you want to do this?"); return static_modint(value | rhs.value); } [[nodiscard]] CP_LIBRARY_USE_CONSTEXPR static_modint operator^(const static_modint rhs) const { CP_LIBRARY_WARN("static_modint::operator^ : Are you sure you want to do this?"); return static_modint(value ^ rhs.value); } [[nodiscard]] CP_LIBRARY_USE_CONSTEXPR static_modint operator<<(const static_modint rhs) const { CP_LIBRARY_WARN("static_modint::operator<< : Are you sure you want to do this?"); return static_modint(static_cast<std::int_least64_t>(value) << rhs.value); } [[nodiscard]] CP_LIBRARY_USE_CONSTEXPR static_modint operator>>(const static_modint rhs) const { CP_LIBRARY_WARN("static_modint::operator>> : Are you sure you want to do this?"); return static_modint(value >> rhs.value, true); } constexpr static_modint& operator+=(const static_modint rhs) noexcept { value += rhs.value; if (value >= modulo) value -= modulo; return *this; } constexpr static_modint& operator-=(const static_modint rhs) noexcept { value -= rhs.value; if (value < 0) value += modulo; return *this; } constexpr static_modint& operator*=(const static_modint rhs) noexcept { value = clamp_ll(static_cast<std::int_least64_t>(value) * rhs.value); return *this; } static_modint& operator/=(const static_modint rhs) { value = clamp_ll(static_cast<std::int_least64_t>(value) * calc_inverse(rhs.value)); return *this; } CP_LIBRARY_USE_CONSTEXPR static_modint& operator%=(const static_modint rhs) { CP_LIBRARY_WARN("static_modint::operator%= : Are you sure you want to do this?"); value %= rhs.value; if (value < 0) value += modulo; return *this; } CP_LIBRARY_USE_CONSTEXPR static_modint& operator&=(const static_modint rhs) { CP_LIBRARY_WARN("static_modint::operator&= : Are you sure you want to do this?"); value &= rhs.value; return *this; } CP_LIBRARY_USE_CONSTEXPR static_modint& operator|=(const static_modint rhs) { CP_LIBRARY_WARN("static_modint::operator|= : Are you sure you want to do this?"); value |= rhs.value; clamp_self(); return *this; } CP_LIBRARY_USE_CONSTEXPR static_modint& operator^=(const static_modint rhs) { CP_LIBRARY_WARN("static_modint::operator^= : Are you sure you want to do this?"); value ^= rhs.value; clamp_self(); return *this; } CP_LIBRARY_USE_CONSTEXPR static_modint& operator<<=(const static_modint rhs) { CP_LIBRARY_WARN("operator<<= : Are you sure you want to do this?"); value = clamp_ll(static_cast<std::int_least64_t>(value) << rhs.value); return *this; } CP_LIBRARY_USE_CONSTEXPR static_modint& operator>>=(const static_modint rhs) { CP_LIBRARY_WARN("operator>>= : Are you sure you want to do this?"); value >>= rhs.value; return *this; } template <typename RhsType> [[nodiscard]] constexpr static_modint operator+(const RhsType rhs) const noexcept { return static_modint(value + clamp_ll(rhs)); } template <typename RhsType> [[nodiscard]] constexpr static_modint operator-(const RhsType rhs) const noexcept { return static_modint(value - clamp_ll(rhs)); } template <typename RhsType> [[nodiscard]] constexpr static_modint operator*(const RhsType rhs) const noexcept { return static_modint(static_cast<std::int_least64_t>(value) * clamp_ll(rhs)); } template <typename RhsType> [[nodiscard]] static_modint operator/(const RhsType rhs) const { std::int_least64_t mul = (rhs > 0) ? calc_inverse(rhs) : -calc_inverse(-rhs); return static_modint(value * mul); } template <typename RhsType> [[nodiscard]] CP_LIBRARY_USE_CONSTEXPR static_modint operator%(const RhsType rhs) const { CP_LIBRARY_WARN("static_modint::operator% : Are you sure you want to do this?"); return static_modint(value % rhs, true); } template <typename RhsType> [[nodiscard]] CP_LIBRARY_USE_CONSTEXPR static_modint operator&(const RhsType rhs) const { CP_LIBRARY_WARN("static_modint::operator& : Are you sure you want to do this?"); return static_modint(value & rhs, true); } template <typename RhsType> [[nodiscard]] CP_LIBRARY_USE_CONSTEXPR static_modint operator|(const RhsType rhs) const { CP_LIBRARY_WARN("static_modint::operator| : Are you sure you want to do this?"); return static_modint(value | rhs); } template <typename RhsType> [[nodiscard]] CP_LIBRARY_USE_CONSTEXPR static_modint operator^(const RhsType rhs) const { CP_LIBRARY_WARN("static_modint::operator^ : Are you sure you want to do this?"); return static_modint(value ^ rhs); } template <typename RhsType> [[nodiscard]] CP_LIBRARY_USE_CONSTEXPR static_modint operator<<(const RhsType rhs) const { CP_LIBRARY_WARN("static_modint::operator<< : Are you sure you want to do this?"); return static_modint(static_cast<std::int_least64_t>(value) << rhs); } template <typename RhsType> [[nodiscard]] CP_LIBRARY_USE_CONSTEXPR static_modint operator>>(const RhsType rhs) const { CP_LIBRARY_WARN("static_modint::operator>> : Are you sure you want to do this?"); return static_modint(value >> rhs, true); } template <typename RhsType> constexpr static_modint& operator+=(const RhsType rhs) noexcept { value = clamp_ll(static_cast<std::int_least64_t>(value) + rhs); return *this; } template <typename RhsType> constexpr static_modint& operator-=(const RhsType rhs) noexcept { value = clamp_ll(static_cast<std::int_least64_t>(value) - rhs); return *this; } template <typename RhsType> constexpr static_modint& operator*=(const RhsType rhs) noexcept { value = clamp_ll(static_cast<std::int_least64_t>(value) * clamp_ll(rhs)); return *this; } template <typename RhsType> static_modint& operator/=(const RhsType rhs) { std::int_least64_t mul = (rhs > 0) ? calc_inverse(rhs) : -calc_inverse(-rhs); value = clamp_ll(value * mul); return *this; } template <typename RhsType> CP_LIBRARY_USE_CONSTEXPR static_modint& operator%=(const RhsType rhs) { CP_LIBRARY_WARN("static_modint::operator%= : Are you sure you want to do this?"); value %= rhs; return *this; } template <typename RhsType> CP_LIBRARY_USE_CONSTEXPR static_modint& operator&=(const RhsType rhs) { CP_LIBRARY_WARN("static_modint::operator&= : Are you sure you want to do this?"); value &= rhs; return *this; } template <typename RhsType> CP_LIBRARY_USE_CONSTEXPR static_modint& operator|=(const RhsType rhs) { CP_LIBRARY_WARN("static_modint::operator|= : Are you sure you want to do this?"); value |= rhs; clamp_self(); return *this; } template <typename RhsType> CP_LIBRARY_USE_CONSTEXPR static_modint& operator^=(const RhsType rhs) { CP_LIBRARY_WARN("static_modint::operator^= : Are you sure you want to do this?"); value ^= rhs; clamp_self(); return *this; } template <typename RhsType> CP_LIBRARY_USE_CONSTEXPR static_modint& operator<<=(const RhsType rhs) { CP_LIBRARY_WARN("operator<<= : Are you sure you want to do this?"); value = clamp_ll(static_cast<std::int_least64_t>(value) << rhs); return *this; } template <typename RhsType> CP_LIBRARY_USE_CONSTEXPR static_modint& operator>>=(const RhsType rhs) { CP_LIBRARY_WARN("operator>>= : Are you sure you want to do this?"); value >>= rhs; return *this; } [[nodiscard]] CP_LIBRARY_USE_CONSTEXPR bool operator!() const { CP_LIBRARY_WARN("static_modint::operator! : Are you sure you want to do this?"); return value == 0; } [[nodiscard]] CP_LIBRARY_USE_CONSTEXPR static_modint operator~() const { CP_LIBRARY_WARN("static_modint::operator~ : Are you sure you want to do this?"); return static_modint(~value); } [[nodiscard]] constexpr static_modint operator-() const noexcept { return static_modint(value == 0 ? 0 : modulo - value, true); } [[nodiscard]] constexpr static_modint& operator+() const noexcept { return *this; } constexpr static_modint& operator++() noexcept { value = ((value + 1 == modulo) ? 0 : value + 1); return *this; } constexpr static_modint& operator--() noexcept { value = ((value == 0) ? modulo - 1 : value - 1); return *this; } constexpr static_modint operator++(int) noexcept { std::int_least32_t res = value; ++(*this); return static_modint(res, true); } constexpr static_modint operator--(int) noexcept { std::int_least32_t res = value; --(*this); return static_modint(res, true); } [[nodiscard]] constexpr bool operator==(const static_modint rhs) const noexcept { return value == rhs.value; } [[nodiscard]] constexpr bool operator!=(const static_modint rhs) const noexcept { return value != rhs.value; } [[nodiscard]] CP_LIBRARY_USE_CONSTEXPR bool operator<(const static_modint rhs) const { CP_LIBRARY_WARN("static_modint::operator< : Are you sure you want to do this?"); return value < rhs.value; } [[nodiscard]] CP_LIBRARY_USE_CONSTEXPR bool operator<=(const static_modint rhs) const { CP_LIBRARY_WARN("static_modint::operator<= : Are you sure you want to do this?"); return value <= rhs.value; } [[nodiscard]] CP_LIBRARY_USE_CONSTEXPR bool operator>(const static_modint rhs) const { CP_LIBRARY_WARN("static_modint::operator> : Are you sure you want to do this?"); return value > rhs.value; } [[nodiscard]] CP_LIBRARY_USE_CONSTEXPR bool operator>=(const static_modint rhs) const { CP_LIBRARY_WARN("static_modint::operator>= : Are you sure you want to do this?"); return value >= rhs.value; } template <typename RhsType> [[nodiscard]] constexpr bool operator==(const RhsType rhs) const noexcept { return value == rhs; } template <typename RhsType> [[nodiscard]] constexpr bool operator!=(const RhsType rhs) const noexcept { return value != rhs; } template <typename RhsType> [[nodiscard]] CP_LIBRARY_USE_CONSTEXPR bool operator<(const RhsType rhs) const { CP_LIBRARY_WARN("static_modint::operator< : Are you sure you want to do this?"); return value < rhs; } template <typename RhsType> [[nodiscard]] CP_LIBRARY_USE_CONSTEXPR bool operator<=(const RhsType rhs) const { CP_LIBRARY_WARN("static_modint::operator<= : Are you sure you want to do this?"); return value <= rhs; } template <typename RhsType> [[nodiscard]] CP_LIBRARY_USE_CONSTEXPR bool operator>(const RhsType rhs) const { CP_LIBRARY_WARN("static_modint::operator> : Are you sure you want to do this?"); return value > rhs; } template <typename RhsType> [[nodiscard]] CP_LIBRARY_USE_CONSTEXPR bool operator>=(const RhsType rhs) const { CP_LIBRARY_WARN("static_modint::operator>= : Are you sure you want to do this?"); return value >= rhs; } [[nodiscard]] constexpr operator std::int_least32_t() const { CP_LIBRARY_WARN("A value of type static_modint has been cast to type std::int_lease32_t."); return value; } //! @brief Read value (64-bit signed integer) from std::istream& is, take modulo, and store it in rhs. //! @return std::istream& is friend std::istream& operator>>(std::istream& is, static_modint& rhs) { std::int_least64_t tmp; is >> tmp; if (tmp < -modulo || modulo <= tmp) tmp %= modulo; if (tmp < 0) tmp += modulo; rhs.value = static_cast<std::int_least32_t>(tmp); return is; } //! @brief Print value to std::ostream& os //! @return std::ostream& os friend std::ostream& operator<<(std::ostream& os, static_modint& rhs) { return os << rhs.value; } //! @return multiplicative inverse [[nodiscard]] static_modint inv() const { return static_modint(calc_inverse(value), true); } //! @tparam index_positive_guaranteed set true if and only if you can promise that index is positive //! @tparam Tp integer type (deduced from parameter) //! @param index index. This must be an integer, but doesn't have to be primitive. //! @return index-th power of the value //! @note Time complexity: O(log(index)) template <bool index_positive_guaranteed = true, typename Tp = std::int_least32_t> [[nodiscard]] static_modint pow(Tp index) const noexcept { if constexpr (!index_positive_guaranteed) { if (value == 0) return static_modint(0, true); if (index == 0) return static_modint(1, true); if (index < 0) return static_modint(value, true).inv().pow<true>(-index); } static_modint res(1, true), base(value, true); while (index > 0) { if ((index & 1) == 1) res *= base; base *= base; index >>= 1; } return res; } //! @return a pair (a, b) such that b > 0, value is equal to a * (mult inverse of b), and (a + b) is minimal [[nodiscard]] constexpr std::pair<std::int_least32_t, std::int_least32_t> to_frac() const noexcept { std::int_least32_t x = modulo - value, y = value, u = 1, v = 1; std::pair<std::int_least32_t, std::int_least32_t> res {value, 1}; std::int_least32_t num = value, den = 1; std::int_least32_t cost = num + den; while (x > 0) { if (x <= num) { std::int_least32_t q = num / x; num = num % x; den += q * u; if (num == 0) break; if (num + den < cost) { cost = num + den; res.first = num; res.second = den; } } std::int_least32_t q = y / x; y = y % x; v += q * u; q = x / y; x = x % y; u += q * v; } return res; } }; template <typename LhsType, std::int_least32_t modulo> [[nodiscard]] constexpr static_modint<modulo> operator+(const LhsType lhs, const static_modint<modulo> rhs) noexcept { return rhs + lhs; } template <typename LhsType, std::int_least32_t modulo> [[nodiscard]] constexpr static_modint<modulo> operator-(const LhsType lhs, const static_modint<modulo> rhs) noexcept { return -rhs + lhs; } template <typename LhsType, std::int_least32_t modulo> [[nodiscard]] constexpr static_modint<modulo> operator*(const LhsType lhs, const static_modint<modulo> rhs) noexcept { return rhs * lhs; } template <typename LhsType, std::int_least32_t modulo> [[nodiscard]] static_modint<modulo> operator/(const LhsType lhs, const static_modint<modulo> rhs) { return rhs.inv() * lhs; } template <typename LhsType, std::int_least32_t modulo> [[nodiscard]] CP_LIBRARY_USE_CONSTEXPR static_modint<modulo> operator%(const LhsType lhs, const static_modint<modulo> rhs) { CP_LIBRARY_WARN("static_modint::operator% : Are you sure you want to do this?"); return static_modint<modulo>(lhs % static_cast<std::int_least32_t>(rhs), true); } template <typename LhsType, std::int_least32_t modulo, std::enable_if_t<std::is_integral_v<LhsType>, std::nullptr_t> = nullptr> [[nodiscard]] CP_LIBRARY_USE_CONSTEXPR static_modint<modulo> operator<<(const LhsType lhs, const static_modint<modulo> rhs) { CP_LIBRARY_WARN("static_modint::operator<< : Are you sure you want to do this?"); return static_modint<modulo>(static_cast<std::int_least64_t>(lhs) << static_cast<std::int_least32_t>(rhs)); } template <typename LhsType, std::int_least32_t modulo, std::enable_if_t<std::is_integral_v<LhsType>, std::nullptr_t> = nullptr> [[nodiscard]] CP_LIBRARY_USE_CONSTEXPR static_modint<modulo> operator>>(const LhsType lhs, const static_modint<modulo> rhs) { CP_LIBRARY_WARN("static_modint::operator>> : Are you sure you want to do this?"); return static_modint<modulo>(lhs >> static_cast<std::int_least32_t>(rhs)); } template <typename LhsType, std::int_least32_t modulo> constexpr LhsType& operator+=(LhsType& lhs, const static_modint<modulo> rhs) noexcept { return lhs += static_cast<std::int_least32_t>(rhs); } template <typename LhsType, std::int_least32_t modulo> constexpr LhsType& operator-=(LhsType& lhs, const static_modint<modulo> rhs) noexcept { return lhs -= static_cast<std::int_least32_t>(rhs); } template <typename LhsType, std::int_least32_t modulo> constexpr LhsType& operator*=(LhsType& lhs, const static_modint<modulo> rhs) noexcept { return lhs *= static_cast<std::int_least32_t>(rhs); } template <typename LhsType, std::int_least32_t modulo> constexpr LhsType& operator/=(LhsType& lhs, const static_modint<modulo> rhs) { return lhs /= static_cast<std::int_least32_t>(rhs); } template <typename LhsType, std::int_least32_t modulo> CP_LIBRARY_USE_CONSTEXPR LhsType& operator%=(LhsType& lhs, const static_modint<modulo> rhs) { CP_LIBRARY_WARN("static_modint::operator%= : Are you sure you want to do this?"); return lhs %= static_cast<std::int_least32_t>(rhs); } template <typename LhsType, std::int_least32_t modulo> CP_LIBRARY_USE_CONSTEXPR LhsType& operator&=(LhsType& lhs, const static_modint<modulo> rhs) { CP_LIBRARY_WARN("static_modint::operator&= : Are you sure you want to do this?"); return lhs &= static_cast<std::int_least32_t>(rhs); } template <typename LhsType, std::int_least32_t modulo> CP_LIBRARY_USE_CONSTEXPR LhsType& operator|=(LhsType& lhs, const static_modint<modulo> rhs) { CP_LIBRARY_WARN("static_modint::operator|= : Are you sure you want to do this?"); return lhs |= static_cast<std::int_least32_t>(rhs); } template <typename LhsType, std::int_least32_t modulo> CP_LIBRARY_USE_CONSTEXPR LhsType& operator^=(LhsType& lhs, const static_modint<modulo> rhs) { CP_LIBRARY_WARN("static_modint::operator^= : Are you sure you want to do this?"); return lhs ^= static_cast<std::int_least32_t>(rhs); } template <typename LhsType, std::int_least32_t modulo> CP_LIBRARY_USE_CONSTEXPR LhsType& operator<<=(LhsType& lhs, const static_modint<modulo> rhs) { CP_LIBRARY_WARN("operator<<= : Are you sure you want to do this?"); return lhs <<= static_cast<std::int_least32_t>(rhs); } template <typename LhsType, std::int_least32_t modulo> CP_LIBRARY_USE_CONSTEXPR LhsType& operator>>=(LhsType& lhs, const static_modint<modulo> rhs) { CP_LIBRARY_WARN("operator>>= : Are you sure you want to do this?"); return lhs >>= static_cast<std::int_least32_t>(rhs); } template <typename LhsType, std::int_least32_t modulo> [[nodiscard]] CP_LIBRARY_USE_CONSTEXPR bool operator<(const LhsType lhs, const static_modint<modulo> rhs) { CP_LIBRARY_WARN("static_modint::operator< : Are you sure you want to do this?"); return lhs < static_cast<std::int_least32_t>(rhs); } template <typename LhsType, std::int_least32_t modulo> [[nodiscard]] CP_LIBRARY_USE_CONSTEXPR bool operator<=(const LhsType lhs, const static_modint<modulo> rhs) { CP_LIBRARY_WARN("static_modint::operator<= : Are you sure you want to do this?"); return lhs < static_cast<std::int_least32_t>(rhs); } template <typename LhsType, std::int_least32_t modulo> [[nodiscard]] CP_LIBRARY_USE_CONSTEXPR bool operator>(const LhsType lhs, const static_modint<modulo> rhs) { CP_LIBRARY_WARN("static_modint::operator> : Are you sure you want to do this?"); return lhs < static_cast<std::int_least32_t>(rhs); } template <typename LhsType, std::int_least32_t modulo> [[nodiscard]] CP_LIBRARY_USE_CONSTEXPR bool operator>=(const LhsType lhs, const static_modint<modulo> rhs) { CP_LIBRARY_WARN("static_modint::operator>= : Are you sure you want to do this?"); return lhs < static_cast<std::int_least32_t>(rhs); } } // namespace lib #undef CP_LIBRARY_USE_CONSTEXPR #ifdef CP_LIBRARY_WARN_NOT_DEFINED # undef CP_LIBRARY_WARN # undef CP_LIBRARY_WARN_NOT_DEFINED # ifdef CP_LIBRARY_WARN # undef CP_LIBRARY_WARN # endif #endif #ifdef CP_LIBRARY_ASSERT_NOT_DEFINED # undef CP_LIBRARY_ASSERT # undef CP_LIBRARY_ASSERT_NOT_DEFINED #endif #endif // CP_LIBRARY_STATIC_MODINT_HPP #line 1 "include/combinatorics/factorial.hpp" //! @file factorial.hpp //! @brief Factorial, Permutation, Combination, Multinomial coefficient #ifndef CP_LIBRARY_FACTORIAL_HPP #define CP_LIBRARY_FACTORIAL_HPP #include <algorithm> #include <array> #line 11 "include/combinatorics/factorial.hpp" #include <numeric> #include <type_traits> #ifndef CP_LIBRARY_WARN # if (CP_LIBRARY_DEBUG_LEVEL >= 1) //! @brief Print warning message //! @note You can suppress the warning by uncommenting the following line # define CP_LIBRARY_WARN(msg) (std::cerr << (msg) << '\n') // # define CP_LIBRARY_WARN(msg) (static_cast<void>(0)) # else # define CP_LIBRARY_WARN(msg) (static_cast<void>(0)) # endif # define CP_LIBRARY_WARN_NOT_DEFINED #endif namespace lib { namespace internal::factorial_hpp { template <typename... Ts> struct is_all_same : std::false_type {}; template <> struct is_all_same<> : std::true_type {}; template <typename Tp> struct is_all_same<Tp> : std::true_type {}; template <typename Tp, typename... Ts> struct is_all_same<Tp, Tp, Ts...> : is_all_same<Tp, Ts...> {}; template <typename... Ts> [[maybe_unused]] constexpr bool is_all_same_v = is_all_same<Ts...>::value; template <class Tp, class... Ts> struct first_type { using type = Tp; }; template <class... Ts> using first_type_t = typename first_type<Ts...>::type; } // namespace internal::factorial_hpp //! @tparam Tp deduced from parameter //! @tparam ReturnType set appropriately if there is a possibility of overflow (e.g. long long, __int128, modint) //! @param n non-negative integer (doesn't have to be primitive) //! @return factorial of n (n!), or number of ways to arrange n distinguishable objects in any order. //! @note Time complexity: O(n) template <typename Tp, typename ReturnType = Tp> [[nodiscard]] ReturnType factorial(const Tp n) { if (n < 0) CP_LIBRARY_WARN("n is negative."); ReturnType res = 1; for (Tp i = 1; i <= n; ++i) res *= i; return res; } //! @tparam Tp deduced from parameters //! @tparam ReturnType set appropriately if there is a possibility of overflow (e.g. long long, __int128, modint) //! @param n non-negative integer (doesn't have to be primitive) //! @param r non-negative integer (doesn't have to be primitive) //! @return nPr, or number of ways to select r out of n distinguishable objects and arrange them in any order. //! @note Time complexity: O(r) template <typename Tp, typename ReturnType = Tp> [[nodiscard]] ReturnType permutation(const Tp n, const Tp r) { if (n == 0) CP_LIBRARY_WARN("n is zero."); if (n < 0) { CP_LIBRARY_WARN("n is negative."); return 0; } if (r < 0) { CP_LIBRARY_WARN("r is negative."); return 0; } if (n < r) { CP_LIBRARY_WARN("n is less than r."); return 0; } ReturnType res = 1; for (Tp i = n - r + 1; i <= n; ++i) res *= i; return res; } //! @tparam Tp deduced from parameters //! @tparam ReturnType set appropriately if there is a possibility of overflow (e.g. long long, __int128, modint) //! @param n non-negative integer (doesn't have to be primitive) //! @param r non-negative integer (doesn't have to be primitive) //! @return nCr, or number of ways to select r out of n distinguishable objects. //! @note Time complexity: O(r) template <typename Tp, typename ReturnType = Tp> [[nodiscard]] ReturnType combination(const Tp n, const Tp r) { if (n == 0) CP_LIBRARY_WARN("n is zero."); if (n < 0) { CP_LIBRARY_WARN("n is negative."); return 0; } if (r < 0) { CP_LIBRARY_WARN("r is negative."); return 0; } if (n < r) { CP_LIBRARY_WARN("n is less than r."); return 0; } ReturnType res = 1; for (Tp i = 1; i <= r; ++i) { res *= (n - r + i); res /= i; } return res; } //! @tparam Tp deduced from parameters //! @tparam ReturnType set appropriately if there is a possibility of overflow (e.g. long long, __int128, modint) //! @tparam Ts deduced from parameters //! @param n non-negative integer //! @param r non-negative integers of same type whose sum is less than or equal to n //! @return Number of ways to arrange n objects when r_1, r_2, ... objects are indistinguishable. //! @note Time complexity: O(n - max(r)) template <typename Tp, typename ReturnType = Tp, typename... Ts> [[nodiscard]] ReturnType multinomial(const Tp n, const Ts... r) { static_assert(internal::factorial_hpp::is_all_same_v<Ts...>); if (n == 0) CP_LIBRARY_WARN("n is zero."); if (n < 0) { CP_LIBRARY_WARN("n is negative."); return 0; } if (((r < 0) || ...)) { CP_LIBRARY_WARN("r... contains negative number."); return 0; } if ((r + ...) > n) { CP_LIBRARY_WARN("Sum of r... is greater than n."); return 0; } std::array<internal::factorial_hpp::first_type_t<Ts...>, sizeof...(Ts)> r_array {r...}; const auto max_idx = std::distance(std::cbegin(r_array), std::max_element(std::cbegin(r_array), std::cend(r_array))); const auto max_r = r_array[max_idx]; unsigned current_den_idx = static_cast<int>(max_idx == 0); internal::factorial_hpp::first_type_t<Ts...> current_den_cnt = 1; ReturnType res = 1; for (Tp i = 1; i <= n - max_r; ++i) { res *= (n - i + 1); res /= current_den_cnt; if (current_den_idx < sizeof...(Ts) - 1 && (current_den_cnt == r_array[current_den_idx] || current_den_idx == max_idx)) { current_den_idx += static_cast<int>(current_den_cnt == r_array[current_den_idx]); current_den_idx += static_cast<int>(current_den_idx == max_idx); current_den_cnt = 1; } else if (current_den_idx == sizeof...(Ts) - 1 && current_den_cnt == r_array[current_den_idx]) { current_den_cnt = 1; } else { ++current_den_cnt; } } return res; } //! @tparam Tp deduced from parameters //! @tparam ReturnType set appropriately if there is a possibility of overflow (e.g. long long, __int128, modint) //! @tparam Container container type (deduced from parameters) //! @param n non-negative integer //! @param r container of non-negative integers whose sum is less than or equal to n //! @return Number of ways to arrange n objects when r[0], r[1], ... objects are indistinguishable. //! @note Time complexity: O(n - max(r)) template <typename Tp, typename ReturnType = Tp, typename Container> [[nodiscard]] ReturnType multinomial(const Tp n, const Container& r) { using Elem = std::decay_t<decltype(*std::cbegin(r))>; if (n == 0) CP_LIBRARY_WARN("n is zero."); if (n < 0) { CP_LIBRARY_WARN("n is negative."); return 0; } if (std::any_of(std::cbegin(r), std::cend(r), [](const auto v) { return v < 0; })) { CP_LIBRARY_WARN("r contains negative number."); return 0; } if (std::reduce(std::cbegin(r), std::cend(r), Elem(0)) > n) { CP_LIBRARY_WARN("Sum of r is greater than n."); return 0; } const auto max_idx = std::distance(std::cbegin(r), std::max_element(std::cbegin(r), std::cend(r))); const auto max_r = r[max_idx]; unsigned current_den_idx = static_cast<int>(max_idx == 0); Elem current_den_cnt = 1; ReturnType res = 1; for (Tp i = 1; i <= n - max_r; ++i) { res *= (n - i + 1); res /= current_den_cnt; if (current_den_idx < std::size(r) - 1 && (current_den_cnt == r[current_den_idx] || current_den_idx == max_idx)) { current_den_idx += static_cast<int>(current_den_cnt == r[current_den_idx]); current_den_idx += static_cast<int>(current_den_idx == max_idx); current_den_cnt = 1; } else if (current_den_idx == std::size(r) - 1 && current_den_cnt == r[current_den_idx]) { current_den_cnt = 1; } else { ++current_den_cnt; } } return res; } //! @tparam Tp deduced from parameters //! @tparam ReturnType set appropriately if there is a possibility of overflow (e.g. long long, __int128, modint) //! @param n non-negative integer (doesn't have to be primitive) //! @param r non-negative integer (doesn't have to be primitive) //! @return nHr, or number of ways to put n indistinguishable balls into r distinguishable bins. //! @note Time complexity: O(r) template <typename Tp, typename ReturnType = Tp> [[nodiscard]] ReturnType stars_and_bars(const Tp n, const Tp r) { return combination<Tp, ReturnType>(n + r - 1, r); } //! @tparam Max upper limit //! @tparam ReturnType value type //! @return std::array which contains 0!, 1!, ..., Max! (Max + 1 numbers) //! @note Time complexity: O(Max) template <std::size_t Max, typename ReturnType> [[nodiscard]] std::array<ReturnType, Max + 1> factorial_array() { std::array<ReturnType, Max + 1> res; res[0] = 1; for (std::size_t i = 1; i <= Max; ++i) res[i] = res[i - 1] * i; return res; } //! @tparam Max upper limit //! @tparam Modint value type (deduced from parameter, must be Modint) //! @param fact factorial of Max (which is the result of factorial or factorial_array) //! @return std::array which contains multiplicative inverse of 0!, 1!, ..., Max! (Max + 1 numbers) //! @note Time complexity: O(Max) template <std::size_t Max, typename Modint> [[nodiscard]] std::array<Modint, Max + 1> factorial_modinv_array(const Modint fact) { std::array<Modint, Max + 1> res; res[Max] = fact.inv(); for (std::size_t i = Max; i > 0; --i) res[i - 1] = res[i] * i; return res; } //! @tparam Size Size of factorial_array and factorial_modinv_array (deduced from parameters) //! @tparam Tp deduced from parameters //! @tparam Modint deduced from parameters //! @param n non-negative integer //! @param r non-negative integer //! @param factorial_array Array that factorial_array() returns //! @param factorial_modinv_array Array that factorial_modinv_array() returns //! @return nPr, or number of ways to select r out of n distinguishable objects and arrange them in any order. //! @note Time complexity: O(1) template <std::size_t Size, typename Modint, typename Tp> [[nodiscard]] Modint permutation(const Tp n, const Tp r, const std::array<Modint, Size>& factorial_array, const std::array<Modint, Size>& factorial_modinv_array) { if (n == 0) CP_LIBRARY_WARN("n is zero."); if (n < 0) { CP_LIBRARY_WARN("n is negative."); return 0; } if (r < 0) { CP_LIBRARY_WARN("r is negative."); return 0; } if (n < r) { CP_LIBRARY_WARN("n is less than r."); return 0; } return factorial_array[n] * factorial_modinv_array[n - r]; } //! @tparam Size Size of factorial_array and factorial_modinv_array (deduced from parameters) //! @tparam Tp deduced from parameters //! @tparam Modint deduced from parameters //! @param n non-negative integer //! @param r non-negative integer //! @param factorial_array Array that factorial_array() returns //! @param factorial_modinv_array Array that factorial_modinv_array() returns //! @return nCr, or number of ways to select r out of n distinguishable objects. //! @note Time complexity: O(1) template <std::size_t Size, typename Modint, typename Tp> [[nodiscard]] Modint combination(const Tp n, const Tp r, const std::array<Modint, Size>& factorial_array, const std::array<Modint, Size>& factorial_modinv_array) { if (n == 0) CP_LIBRARY_WARN("n is zero."); if (n < 0) { CP_LIBRARY_WARN("n is negative."); return 0; } if (r < 0) { CP_LIBRARY_WARN("r is negative."); return 0; } if (n < r) { CP_LIBRARY_WARN("n is less than r."); return 0; } return factorial_array[n] * factorial_modinv_array[n - r] * factorial_modinv_array[r]; } //! @tparam Size Size of factorial_array and factorial_modinv_array (deduced from parameters) //! @tparam Modint deduced from parameters //! @tparam Tp deduced from parameters //! @tparam Ts deduced from parameters //! @param n non-negative integer //! @param r non-negative integers whose sum is less than or equal to n //! @param factorial_array Array that factorial_array() returns //! @param factorial_modinv_array Array that factorial_modinv_array() returns //! @return Number of ways to arrange n objects when r_1, r_2, ... objects are indistinguishable. //! @note Time complexity: O(sizeof...(r)) template <std::size_t Size, typename Modint, typename Tp, typename... Ts> [[nodiscard]] Modint multinomial(const Tp n, const Ts... r, const std::array<Modint, Size>& factorial_array, const std::array<Modint, Size>& factorial_modinv_array) { if (n == 0) CP_LIBRARY_WARN("n is zero."); if (n < 0) { CP_LIBRARY_WARN("n is negative."); return 0; } if (((r < 0) || ...)) { CP_LIBRARY_WARN("r contains negative number."); return 0; } if ((r + ...) > n) { CP_LIBRARY_WARN("Sum of r... is greater than n."); return 0; } return factorial_array[n] * ((factorial_modinv_array[r]) * ...); } //! @tparam Size Size of factorial_array and factorial_modinv_array (deduced from parameters) //! @tparam Modint deduced from parameters //! @tparam Tp deduced from parameters //! @tparam container type (deduced from parameters) //! @param n non-negative integer //! @param r container of non-negative integers whose sum is less than or equal to n //! @param factorial_array Array that factorial_array() returns //! @param factorial_modinv_array Array that factorial_modinv_array() returns //! @return Number of ways to arrange n objects when r[0], r[1], ... objects are indistinguishable. //! @note Time complexity: O(size(r)) template <std::size_t Size, typename Modint, typename Tp, typename Container> [[nodiscard]] Modint multinomial(const Tp n, const Container& r, const std::array<Modint, Size>& factorial_array, const std::array<Modint, Size>& factorial_modinv_array) { using Elem = std::decay_t<decltype(*std::cbegin(r))>; if (n == 0) CP_LIBRARY_WARN("n is zero."); if (n < 0) { CP_LIBRARY_WARN("n is negative."); return 0; } if (std::any_of(std::cbegin(r), std::cend(r), [](const auto v) { return v < 0; })) { CP_LIBRARY_WARN("r contains negative number."); return 0; } if (std::reduce(std::cbegin(r), std::cend(r), Elem(0)) > n) { CP_LIBRARY_WARN("Sum of r is greater than n."); return 0; } return factorial_array[n] * std::reduce(std::cbegin(r), std::cend(r), Modint(1), [&](const Modint res, const Elem e) { return res * factorial_modinv_array[e]; }); } //! @tparam Size Size of factorial_array and factorial_modinv_array (deduced from parameters) //! @tparam Tp deduced from parameters //! @tparam Modint deduced from parameters //! @param n non-negative integer //! @param r non-negative integers whose sum is equal to n //! @param factorial_array Array that factorial_array() returns //! @param factorial_modinv_array Array that factorial_modinv_array() returns //! @return nHr, or number of ways to put n indistinguishable balls into r distinguishable bins. //! @note Time complexity: O(1) template <std::size_t Size, typename Modint, typename Tp> [[nodiscard]] Modint stars_and_bars(const Tp n, const Tp r, const std::array<Modint, Size>& factorial_array, const std::array<Modint, Size>& factorial_modinv_array) { return combination(n + r - 1, r, factorial_array, factorial_modinv_array); } } // namespace lib #ifdef CP_LIBRARY_WARN_NOT_DEFINED # undef CP_LIBRARY_WARN # undef CP_LIBRARY_WARN_NOT_DEFINED # ifdef CP_LIBRARY_WARN # undef CP_LIBRARY_WARN # endif #endif #endif #line 6 "test/combinatorics/factorial/2.test.cpp" int main() { int N, A, B; std::cin >> N >> A >> B; using mint = lib::static_modint<1000000007>; mint res = mint(2).pow(N) - 1; res -= lib::combination<int, mint>(N, A); res -= lib::combination<int, mint>(N, B); std::cout << res << '\n'; }