Submission #1243137

#TimeUsernameProblemLanguageResultExecution timeMemory
1243137skibidiheheSkyscraper (JOI16_skyscraper)C++20
0 / 100
0 ms580 KiB
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

#define fi first
#define se second
#define pb push_back
#define taskname ""

const ll MOD = 1e9 + 7;

ll dp[105][105][1005][3];
ll a[105];

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, L;
    cin >> n >> L;
    for(int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    sort(a + 1, a + n + 1);
    // Đặt giá trị "infinity" ở vị trí n+1 để tiện tính diff
    a[n + 1] = 10000;

    if(n == 1) {
        cout << 1 << '\n';
        return 0;
    }

    // Khởi tạo cho i = 2 (đã đặt a[1] và a[2])
    int diff0 = a[2] - a[1];
    if(diff0 <= L) dp[2][1][diff0][1] = 2;          // đặt a[1] vào một đầu, có 2 cách
    if(2 * diff0 <= L) dp[2][1][2 * diff0][0] = 1;  // đặt a[1] vào giữa, 1 cách

    // DP chuyển tiếp từ i đến i+1
    for(int i = 2; i < n; i++) {
        int diff = a[i + 1] - a[i];
        for(int j = 1; j <= i - 1; j++) {
            for(int cost = 0; cost <= L; cost++) {
                for(int z = 0; z < 3; z++) {
                    ll cur = dp[i][j][cost][z];
                    if(cur == 0) continue;

                    // 1) Chèn vào một đầu
                    if(z < 2) {
                        int upgrade = 2 * j - z - 1;
                        int newCost = cost + diff * upgrade;
                        if(newCost <= L) {
                            // gắn vào CC hiện tại
                            if(i + 1 == n) {
                                dp[i + 1][j][newCost][z + 1] = (dp[i + 1][j][newCost][z + 1] + cur * (2 - z)) % MOD;
                            } else if(j - z > 0) {
                                dp[i + 1][j][newCost][z + 1] = (dp[i + 1][j][newCost][z + 1] + cur * (2 - z) * (j - z)) % MOD;
                            }
                            // tạo CC mới
                            int upgradeNew = 2 * j - z + 1;
                            int costNewCC = cost + diff * upgradeNew;
                            if(costNewCC <= L) {
                                dp[i + 1][j + 1][costNewCC][z + 1] = (dp[i + 1][j + 1][costNewCC][z + 1] + cur * (2 - z)) % MOD;
                            }
                        }
                    }

                    // 2) Không chèn vào đầu
                    // 2.1 Tạo CC mới
                    {
                        int upgrade = 2 * j - z + 2;
                        int newCost = cost + diff * upgrade;
                        if(newCost <= L) {
                            dp[i + 1][j + 1][newCost][z] = (dp[i + 1][j + 1][newCost][z] + cur) % MOD;
                        }
                    }
                    // 2.2 Gắn vào một CC hiện hữu
                    {
                        int upgrade = 2 * j - z;
                        int newCost = cost + diff * upgrade;
                        if(newCost <= L) {
                            dp[i + 1][j][newCost][z] = (dp[i + 1][j][newCost][z] + cur * (2 * j - z)) % MOD;
                        }
                    }
                    // 2.3 Merge hai CC
                    if(j >= 2) {
                        int upgrade = 2 * j - z - 2;
                        int newCost = cost + diff * upgrade;
                        if(newCost <= L && (i + 1 == n || j > 2 || z < 2)) {
                            if(z == 0) {
                                dp[i + 1][j - 1][newCost][z] = (dp[i + 1][j - 1][newCost][z] + cur * j * (j - 1)) % MOD;
                            } else if(z == 1) {
                                dp[i + 1][j - 1][newCost][z] = (dp[i + 1][j - 1][newCost][z] + cur * (j - 1) * (j - 1)) % MOD;
                            } else {
                                if(i + 1 == n) {
                                    dp[i + 1][j - 1][newCost][z] = (dp[i + 1][j - 1][newCost][z] + cur) % MOD;
                                } else {
                                    dp[i + 1][j - 1][newCost][z] = (dp[i + 1][j - 1][newCost][z] + cur * (j - 2) * (j - 1)) % MOD;
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    // Tính kết quả: còn đúng 1 CC, hai đầu đã lấp
    ll answer = 0;
    for(int cost = 0; cost <= L; cost++) {
        answer = (answer + dp[n][1][cost][2]) % MOD;
    }
    cout << answer << "\n";
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...