Skip to the content.

:heavy_check_mark: library/mod/MintUtility.hpp

Depends on

Verified with

Code

template <typename MINT> class MintUtility {
    std::vector<MINT> fact_ = {MINT::raw(1)};
    std::vector<MINT> inv_fact_{MINT::raw(1)};
    int S = 1; // 今のサイズ

    void extend(const int n) {
        if (n < S)
            return;
        const int preS = S;
        do {
            S <<= 1;
        } while (S <= n);

        fact_.resize(S);
        for (int i = preS; i < S; i++)
            fact_[i] = fact_[i - 1] * MINT::raw(i);

        inv_fact_.resize(S);
        inv_fact_.back() = fact_.back().inv();
        for (int i = S - 1; i > preS; i--)
            inv_fact_[i - 1] = inv_fact_[i] * MINT::raw(i);
    }

  public:
    MINT fact(const int n) {
        assert(n >= 0);
        extend(n);
        return fact_[n];
    }
    MINT inv_fact(const int n) {
        assert(n >= 0);
        extend(n);
        return inv_fact_[n];
    }
    MINT nCk(const int n, const int k) {
        if (k < 0 || n < k)
            return MINT::raw(0);
        extend(n);
        return fact_[n] * inv_fact_[k] * inv_fact_[n - k];
    }
    MINT nPk(const int n, const int k) {
        if (k < 0 || n < k)
            return MINT::raw(0);
        extend(n);
        return fact_[n] * inv_fact_[n - k];
    }
    MINT nHk(const int n, const int k) {
        return (n == 0 and k == 0 ? 1 : nCk(n + k - 1, k));
    }
};
#line 1 "library/mod/MintUtility.hpp"
template <typename MINT> class MintUtility {
    std::vector<MINT> fact_ = {MINT::raw(1)};
    std::vector<MINT> inv_fact_{MINT::raw(1)};
    int S = 1; // 今のサイズ

    void extend(const int n) {
        if (n < S)
            return;
        const int preS = S;
        do {
            S <<= 1;
        } while (S <= n);

        fact_.resize(S);
        for (int i = preS; i < S; i++)
            fact_[i] = fact_[i - 1] * MINT::raw(i);

        inv_fact_.resize(S);
        inv_fact_.back() = fact_.back().inv();
        for (int i = S - 1; i > preS; i--)
            inv_fact_[i - 1] = inv_fact_[i] * MINT::raw(i);
    }

  public:
    MINT fact(const int n) {
        assert(n >= 0);
        extend(n);
        return fact_[n];
    }
    MINT inv_fact(const int n) {
        assert(n >= 0);
        extend(n);
        return inv_fact_[n];
    }
    MINT nCk(const int n, const int k) {
        if (k < 0 || n < k)
            return MINT::raw(0);
        extend(n);
        return fact_[n] * inv_fact_[k] * inv_fact_[n - k];
    }
    MINT nPk(const int n, const int k) {
        if (k < 0 || n < k)
            return MINT::raw(0);
        extend(n);
        return fact_[n] * inv_fact_[n - k];
    }
    MINT nHk(const int n, const int k) {
        return (n == 0 and k == 0 ? 1 : nCk(n + k - 1, k));
    }
};
Back to top page