Submission #5942337


Source Code Expand

/* Blog: https://misteer.hatenablog.com/entry/diverta2019-2-E */

#include <iostream>
#include <vector>

template <int MOD>
class ModInt {
    using lint = long long;

public:
    int val;

    // constructor
    ModInt(lint v = 0) : val(v % MOD) {
        if (val < 0) val += MOD;
    };

    // assignment
    ModInt& operator=(const ModInt& x) {
        if (this != &x) { this->val = x.val; }
        return *this;
    }

    // unary operator
    ModInt operator+() const { return ModInt(val); }
    ModInt operator-() const { return ModInt(MOD - val); }
    ModInt operator~() const { return *this ^ (MOD - 2); }

    // increment / decrement
    ModInt& operator++() { return *this += 1; }
    ModInt& operator--() { return *this -= 1; }
    ModInt operator++(int) {
        ModInt before = *this;
        ++(*this);
        return before;
    }
    ModInt operator--(int) {
        ModInt before = *this;
        --(*this);
        return before;
    }

    // arithmetic
    ModInt operator+(const ModInt& x) const { return ModInt(*this) += x; }
    ModInt operator-(const ModInt& x) const { return ModInt(*this) -= x; }
    ModInt operator*(const ModInt& x) const { return ModInt(*this) *= x; }
    ModInt operator%(const ModInt& x) const { return ModInt(*this) %= x; }
    ModInt operator/(const ModInt& x) const { return ModInt(*this) /= x; }
    ModInt operator^(const ModInt& x) const { return ModInt(*this) ^= x; }

    // compound assignment
    ModInt& operator+=(const ModInt& x) {
        if ((val += x.val) >= MOD) val -= MOD;
        return *this;
    }
    ModInt& operator-=(const ModInt& x) {
        if ((val -= x.val) < 0) val += MOD;
        return *this;
    }
    ModInt& operator*=(const ModInt& x) {
        val = lint(val) * x.val % MOD;
        return *this;
    }
    ModInt& operator%=(const ModInt& x) {
        val %= x.val;
        return *this;
    }
    ModInt& operator/=(const ModInt& x) { return *this *= ~x; }
    ModInt& operator^=(const ModInt& x) {
        int n = x.val;
        ModInt b = *this;
        if (n < 0) n = -n, b = ~b;

        *this = 1;
        while (n > 0) {
            if (n & 1) *this *= b;
            n >>= 1;
            b *= b;
        }
        return *this;
    }

    // compare
    bool operator==(const ModInt& b) const { return val == b.val; }
    bool operator!=(const ModInt& b) const { return val != b.val; }
    bool operator<(const ModInt& b) const { return val < b.val; }
    bool operator<=(const ModInt& b) const { return val <= b.val; }
    bool operator>(const ModInt& b) const { return val > b.val; }
    bool operator>=(const ModInt& b) const { return val >= b.val; }

    // I/O
    friend std::ostream& operator<<(std::ostream& os, const ModInt& x) noexcept { return os << x.val; }
    friend std::istream& operator>>(std::istream& is, ModInt& x) noexcept { return is >> x.val; }
};

template <int MOD>
class Combination {
    using mint = ModInt<MOD>;

private:
    int MAX_V;
    std::vector<mint> f, invf;

public:
    explicit Combination(int N)
        : MAX_V(N), f(MAX_V + 1), invf(MAX_V + 1) {
        f[0] = 1;
        for (int i = 1; i <= MAX_V; ++i) {
            f[i] = f[i - 1] * i;
        }

        invf[MAX_V] = ~f[MAX_V];
        for (int i = MAX_V - 1; i >= 0; --i) {
            invf[i] = invf[i + 1] * (i + 1);
        }
    }

    mint fact(int n) const { return f[n]; }
    mint invfact(int n) const { return invf[n]; }
    mint perm(int a, int b) const {
        return a < b ? mint(0) : f[a] * invf[a - b];
    }
    mint comb(int a, int b) const {
        return a < b ? mint(0) : f[a] * invf[a - b] * invf[b];
    }
};

using namespace std;

constexpr int MOD = 1e9 + 7;
using mint = ModInt<MOD>;
const Combination<MOD> C(1 << 20);

int main() {
    /* ----- 入力 ----- */
    int N, H, D;
    cin >> N >> H >> D;

    /* ----- 1! + ... + N! ----- */
    mint fsum = 0;
    for (int l = 1; l <= N; ++l) {
        fsum += C.fact(l);
    }

    /* ----- DP ----- */
    vector<mint> dp(H + 1, 0), dpsum(H + 1, 0);
    dp[0] = dpsum[0] = C.fact(N) / fsum;
    // dp[h] = ブロック数の最大値がhで、そのような山の数が1個となるような操作数

    for (int h = 1; h <= H; ++h) {
        dp[h] = fsum * (dpsum[h - 1] -
                        (h - D - 1 >= 0 ? dpsum[h - D - 1] : 0));
        dpsum[h] = dpsum[h - 1] + dp[h];
    }

    cout << dp[H] << endl;
    return 0;
}

Submission Info

Submission Time
Task E - Balanced Piles
User Tiramister
Language C++14 (GCC 5.4.1)
Score 800
Code Size 4574 Byte
Status AC
Exec Time 34 ms
Memory 16256 KiB

Judge Result

Set Name Sample All
Score / Max Score 0 / 0 800 / 800
Status
AC × 3
AC × 42
Set Name Test Cases
Sample s1.txt, s2.txt, s3.txt
All 01.txt, 02.txt, 03.txt, 04.txt, 05.txt, 06.txt, 07.txt, 08.txt, 09.txt, 10.txt, 11.txt, 12.txt, 13.txt, 14.txt, 15.txt, 16.txt, 17.txt, 18.txt, 19.txt, 20.txt, 21.txt, 22.txt, 23.txt, 24.txt, 25.txt, 26.txt, 27.txt, 28.txt, 29.txt, 30.txt, 31.txt, 32.txt, 33.txt, 34.txt, 35.txt, 36.txt, 37.txt, 38.txt, 39.txt, s1.txt, s2.txt, s3.txt
Case Name Status Exec Time Memory
01.txt AC 19 ms 8448 KiB
02.txt AC 19 ms 8448 KiB
03.txt AC 19 ms 8448 KiB
04.txt AC 19 ms 8448 KiB
05.txt AC 19 ms 8448 KiB
06.txt AC 19 ms 8448 KiB
07.txt AC 19 ms 8448 KiB
08.txt AC 19 ms 8448 KiB
09.txt AC 26 ms 12416 KiB
10.txt AC 28 ms 13568 KiB
11.txt AC 31 ms 15744 KiB
12.txt AC 19 ms 8576 KiB
13.txt AC 22 ms 10624 KiB
14.txt AC 20 ms 9344 KiB
15.txt AC 23 ms 10752 KiB
16.txt AC 19 ms 8448 KiB
17.txt AC 19 ms 8448 KiB
18.txt AC 20 ms 8448 KiB
19.txt AC 19 ms 8448 KiB
20.txt AC 19 ms 8448 KiB
21.txt AC 24 ms 10880 KiB
22.txt AC 28 ms 13312 KiB
23.txt AC 33 ms 16128 KiB
24.txt AC 30 ms 14720 KiB
25.txt AC 21 ms 8960 KiB
26.txt AC 33 ms 16256 KiB
27.txt AC 34 ms 16256 KiB
28.txt AC 33 ms 16256 KiB
29.txt AC 34 ms 16256 KiB
30.txt AC 34 ms 16256 KiB
31.txt AC 34 ms 16256 KiB
32.txt AC 34 ms 16256 KiB
33.txt AC 34 ms 16256 KiB
34.txt AC 34 ms 16256 KiB
35.txt AC 34 ms 16256 KiB
36.txt AC 34 ms 16256 KiB
37.txt AC 34 ms 16256 KiB
38.txt AC 19 ms 8448 KiB
39.txt AC 32 ms 16256 KiB
s1.txt AC 19 ms 8448 KiB
s2.txt AC 19 ms 8448 KiB
s3.txt AC 19 ms 8576 KiB