#line 1 "main.cpp" #define PROBLEM "https://yukicoder.me/problems/no/117" #line 2 "/Users/kodamankod/Desktop/Programming/Library/algebraic/factorials.cpp" #include #include template class factorials { public: using value_type = T; static constexpr size_t size = N; public: std::array fact{}; std::array fact_inv{}; factorials() { fact.front() = value_type(1); for (size_t i = 1; i <= size; ++i) { fact[i] = fact[i - 1] * value_type(i); } fact_inv.back() = ~fact.back(); for (size_t i = size; i > 0; --i) { fact_inv[i - 1] = fact_inv[i] * value_type(i); } } value_type operator () (size_t n, size_t r) const { return fact[n] * fact_inv[n - r] * fact_inv[r]; } }; #line 2 "/Users/kodamankod/Desktop/Programming/Library/algebraic/modular.cpp" #include #include template class modular { public: using value_type = uint32_t; using max_type = uint64_t; static constexpr value_type mod = Modulus; static constexpr value_type get_mod() noexcept { return mod; } static_assert(mod >= 2, "invalid mod :: smaller than 2"); static_assert(mod < (value_type(1) << 31), "invalid mod :: over 2^31"); template static constexpr value_type normalize(T value_) noexcept { if (value_ < 0) { value_ = -value_; value_ %= mod; if (value_ == 0) return 0; return mod - value_; } return value_ % mod; } private: value_type value; public: constexpr modular() noexcept : value(0) { } template explicit constexpr modular(T value_) noexcept : value(normalize(value_)) { } template explicit constexpr operator T() const noexcept { return static_cast(value); } constexpr value_type get() const noexcept { return value; } constexpr modular operator - () const noexcept { return modular(mod - value); } constexpr modular operator ~ () const noexcept { return inverse(); } constexpr value_type &extract() noexcept { return value; } constexpr modular inverse() const noexcept { return power(mod - 2); } constexpr modular power(max_type exp) const noexcept { modular res(1), mult(*this); while (exp > 0) { if (exp & 1) res *= mult; mult *= mult; exp >>= 1; } return res; } constexpr modular operator + (const modular &rhs) const noexcept { return modular(*this) += rhs; } constexpr modular& operator += (const modular &rhs) noexcept { if ((value += rhs.value) >= mod) value -= mod; return *this; } constexpr modular operator - (const modular &rhs) const noexcept { return modular(*this) -= rhs; } constexpr modular& operator -= (const modular &rhs) noexcept { if ((value += mod - rhs.value) >= mod) value -= mod; return *this; } constexpr modular operator * (const modular &rhs) const noexcept { return modular(*this) *= rhs; } constexpr modular& operator *= (const modular &rhs) noexcept { value = (max_type) value * rhs.value % mod; return *this; } constexpr modular operator / (const modular &rhs) const noexcept { return modular(*this) /= rhs; } constexpr modular& operator /= (const modular &rhs) noexcept { return (*this) *= rhs.inverse(); } constexpr bool zero() const noexcept { return value == 0; } constexpr bool operator == (const modular &rhs) const noexcept { return value == rhs.value; } constexpr bool operator != (const modular &rhs) const noexcept { return value != rhs.value; } friend std::ostream& operator << (std::ostream &stream, const modular &rhs) { return stream << rhs.value; } }; #line 6 "main.cpp" #line 8 "main.cpp" using m32 = modular<1000000007>; factorials fact; m32 comb(size_t N, size_t K) { if (N < K) return m32(0); return fact(N, K); } m32 perm(size_t N, size_t K) { if (N < K) return m32(0); return fact.fact[N] * fact.fact_inv[N - K]; } m32 homo(size_t N, size_t K) { if (N == 0) return m32(0); return fact(N + K - 1, K); } int main() { size_t T; std::cin >> T; while (T--) { char type, dust; size_t N, K; std::cin >> type >> dust >> N >> dust >> K >> dust; if (type == 'C') std::cout << comb(N, K) << '\n'; if (type == 'P') std::cout << perm(N, K) << '\n'; if (type == 'H') std::cout << homo(N, K) << '\n'; } }