cp-library-cpp

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub naskya/cp-library-cpp

:heavy_check_mark: test/combinatorics/factorial/2.test.cpp

Depends on

Code

#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';
}
Back to top page