제출 #1343135

#제출 시각아이디문제언어결과실행 시간메모리
1343135tfgsSkyscraper (JOI16_skyscraper)C++20
100 / 100
48 ms24380 KiB
#include <bits/stdc++.h>

#define int int64_t
const int inf = 1e18;

using namespace std;

#define ft front()
#define bk back()
#define pb push_back
#define ins insert
#define lb lower_bound
#define ub upper_bound
#define all(x) begin(x), end(x)
#define len(x) int(size(x))
#define pct __builtin_popcount
#define clz __builtin_clz
int bits(int x) {
    return 63 - clz(x);
}
int p2(int x) {
    return int(1) << x;
}

template<class T>
bool ckmax(T& a, const T& b) {
    return a < b ? a = b, 1 : 0;
}
template<class T>
bool ckmin(T& a, const T& b) {
    return a > b ? a = b, 1 : 0;
}


template<class T> using V = vector<T>;
using vi = V<int>;
using vb = V<bool>;
using ai2 = array<int, 2>;
using ai3 = array<int, 3>;
using ai4 = array<int, 4>;

template<class T, class U>
void erase(T& aa, const U& x) {
    auto it = aa.find(x);
    assert(it != end(aa));
    aa.erase(it);
}

void ps() { cerr << '\n'; }
template<class T, class... Ts> void ps(const T& x, const Ts&... xs) {
    cerr << x;
    if (sizeof...(xs))
        cerr << ' ';
    ps(xs...);
}

const int P = 1e9 + 7;

void add(int& a, int b) {
    a += b;
    if (a < 0)
        a += P;
    if (a >= P)
        a -= P;
}

int fadd(int a, int b) {
    add(a, b);
    return a;
}

void mul(int& a, int b) {
    a = int64_t(a) * b % P;
}

int fmul(int a, int b) {
    mul(a, b);
    return a;
}

const int N = 100, L = 1000;
int dp[N + 1][N + 1][L + 1][3];

void solve() {
    int n, max_cost;
    cin >> n >> max_cost;
    vi aa(n);
    for (auto& x : aa)
        cin >> x;
    sort(all(aa));
    if (n == 1) {
        cout << 1 << '\n';
        return;
    }

    // dp[i][j][k][l] = # permutations which 
    // - processed the first i values 
    // - have j components
    // - have cost k if ? were replaced with aa[i]
    // - filled in l <= 2 of the edge values
    dp[0][0][0][0] = 1;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j <= i; j++) { 
            for (int k = 0; k <= max_cost; k++) {
                for (int l = 0; l <= 2; l++) if (dp[i][j][k][l]) {
                    if (l == 2)
                        assert(j > 1);

                    auto cnt_qm_blocks = j + 1 - l;
                    auto cnt_edges = 2 * j - l;

                    // create new cc
                    {
                        int dk = 0;
                        if (i + 1 < n)
                            dk += (aa[i + 1] - aa[i]) * (cnt_edges + 2);
                        if (k + dk <= max_cost)
                            add(dp[i + 1][j + 1][k + dk][l], fmul(j + 1 - l, dp[i][j][k][l]));
                    }

                    // create new cc (side)
                    if (l < 2) {
                        int dk = 0;
                        if (i + 1 < n)
                            dk += (aa[i + 1] - aa[i]) * (cnt_edges + 1);
                        if (k + dk <= max_cost)
                            add(dp[i + 1][j + 1][k + dk][l + 1], fmul(2 - l, dp[i][j][k][l]));
                    }

                    // merge two ccs
                    if (j > 1 && !(l == 2 && j == 2 && i < n - 1)) {
                        int dk = 0;
                        if (i + 1 < n)
                            dk += (aa[i + 1] - aa[i]) * (cnt_edges - 2);
                        if (k + dk <= max_cost)
                            add(dp[i + 1][j - 1][k + dk][l], fmul(j - 1, dp[i][j][k][l]));
                    }

                    // glue to one side of a cc 
                    if (j) {
                        int dk = 0;
                        if (i + 1 < n)
                            dk += (aa[i + 1] - aa[i]) * cnt_edges;
                        if (k + dk <= max_cost)
                            add(dp[i + 1][j][k + dk][l], fmul(2 * j - l, dp[i][j][k][l]));
                    }

                    // glue to one side of a cc and become side
                    if (j && l < 2 && !(l == 1 && j == 1 && i < n - 1)) {
                        int dk = 0;
                        assert(cnt_edges);
                        if (i + 1 < n)
                            dk += (aa[i + 1] - aa[i]) * (cnt_edges - 1);
                        if (k + dk <= max_cost)
                            add(dp[i + 1][j][k + dk][l + 1], fmul(2 - l, dp[i][j][k][l]));
                    }
                }
            }
        }
    }

    int ans = 0;
    for (int k = 0; k <= max_cost; k++) {
        // ps(k, dp[n][1][k][2]);
        add(ans, dp[n][1][k][2]);
    }
    cout << ans << '\n';
}

signed main() {
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(0);
    solve();
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...