#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdlib>
#include <map>
#define int long long
using namespace std;
// int code(int n, int l, vector<int> &heights) {
// sort(heights.begin(), heights.end());
// heights.push_back(1001);
// vector<vector<vector<vector<int>>>> dp(n + 1, vector<vector<vector<int>>>(n + 1, vector<vector<int>>(l + 1, vector<int>(3, 0))));
// dp[0][0][0][0] = 1;
// for (int i = 1; i <= n; ++i) {
// for (int j = 1; j <= i; ++j) {
// for (int k = 0; k <= l; ++k) {
// for (int e = 0; e < 3; ++e) {
// // cout << i << ' ' << j << ' ' << k << ' ' << e << '\n';
// if (i + j - e > n || k < (2 * j - e) * (heights[i] - heights[i - 1]) || (i < n && j == 1 && e == 2)) continue;
// // cout << "if\n";
// int newTot = k - (2 * j - e) * (heights[i] - heights[i - 1]);
// // case 1: adding new building as new segment not at edge
// dp[i][j][k][e] += dp[i - 1][j - 1][newTot][e];
// // cout << "case 1\n";
// // case 2: adding new building as new segment at edge
// if (e) dp[i][j][k][e] += (3 - e) * dp[i - 1][j - 1][newTot][e - 1];
// // cout << "case 2\n";
// // case 3: adding new building onto segment, not merging segments, not onto edge
// dp[i][j][k][e] += (2 * j - e) * dp[i - 1][j][newTot][e];
// // cout << "case 3\n";
// // case 4: adding new building onto segment, at edge
// if (e == 1) dp[i][j][k][e] += 2 * j * dp[i - 1][j][newTot][e - 1];
// else if (e == 2) {
// if (j == 1) dp[i][j][k][e] += dp[i - 1][j][newTot][e - 1];
// else dp[i][j][k][e] += (j - 1) * dp[i - 1][j][newTot][e - 1];
// }
// // cout << "case 4\n";
// // case 5: adding new building onto segment, merging two
// if (e == 0) dp[i][j][k][e] += j * (j + 1) * dp[i - 1][j + 1][newTot][e];
// else if (e == 1) dp[i][j][k][e] += j * j * dp[i - 1][j + 1][newTot][e];
// else if (j == 1) dp[i][j][k][e] += dp[i - 1][j + 1][newTot][e];
// else dp[i][j][k][e] += j * (j - 1) * dp[i - 1][j + 1][newTot][e];
// // cout << "case 5\n";
// dp[i][j][k][e] %= 1'000'000'007;
// // cout << i << ' ' << j << ' ' << k << ' ' << e << ' ' << dp[i][j][k][e] << '\n';
// }
// }
// }
// }
// int res = 0;
// for (int i = 0; i <= l; ++i) {
// res += dp[n][1][i][2];
// res %= 1'000'000'007;
// }
// heights.pop_back();
// return res;
// }
// int bruteforce(int n, int l, vector<int> &heights) {
// sort(heights.begin(), heights.end());
// int res = 0;
// do {
// int cur = 0;
// for (int i = 0; i < n - 1; ++i) cur += abs(heights[i] - heights[i + 1]);
// res += (cur <= l);
// } while (next_permutation(heights.begin(), heights.end()));
// return res;
// }
signed main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
int n, l; cin >> n >> l;
vector<int> heights(n);
for (int &i : heights) cin >> i;
sort(heights.begin(), heights.end());
heights.push_back(1001);
vector<vector<vector<vector<int>>>> dp(n + 1, vector<vector<vector<int>>>(n + 1, vector<vector<int>>(l + 1, vector<int>(3, 0))));
dp[0][0][0][0] = 1;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= i; ++j) {
for (int k = 0; k <= l; ++k) {
for (int e = 0; e < 3; ++e) {
// cout << i << ' ' << j << ' ' << k << ' ' << e << '\n';
if (i + j - e > n || k < (2 * j - e) * (heights[i] - heights[i - 1]) || (i < n && j == 1 && e == 2)) continue;
// cout << "if\n";
int newTot = k - (2 * j - e) * (heights[i] - heights[i - 1]);
// case 1: adding new building as new segment not at edge
dp[i][j][k][e] += dp[i - 1][j - 1][newTot][e];
// cout << "case 1\n";
// case 2: adding new building as new segment at edge
if (e) dp[i][j][k][e] += (3 - e) * dp[i - 1][j - 1][newTot][e - 1];
// cout << "case 2\n";
// case 3: adding new building onto segment, not merging segments, not onto edge
dp[i][j][k][e] += (2 * j - e) * dp[i - 1][j][newTot][e];
// cout << "case 3\n";
// case 4: adding new building onto segment, at edge
if (e == 1) dp[i][j][k][e] += 2 * j * dp[i - 1][j][newTot][e - 1];
else if (e == 2) {
if (j == 1) dp[i][j][k][e] += dp[i - 1][j][newTot][e - 1];
else dp[i][j][k][e] += (j - 1) * dp[i - 1][j][newTot][e - 1];
}
// cout << "case 4\n";
// case 5: adding new building onto segment, merging two
if (e == 0) dp[i][j][k][e] += j * (j + 1) * dp[i - 1][j + 1][newTot][e];
else if (e == 1) dp[i][j][k][e] += j * j * dp[i - 1][j + 1][newTot][e];
else if (j == 1) dp[i][j][k][e] += dp[i - 1][j + 1][newTot][e];
else dp[i][j][k][e] += j * (j - 1) * dp[i - 1][j + 1][newTot][e];
// cout << "case 5\n";
dp[i][j][k][e] %= 1'000'000'007;
// cout << i << ' ' << j << ' ' << k << ' ' << e << ' ' << dp[i][j][k][e] << '\n';
}
}
}
}
int res = 0;
for (int i = 0; i <= l; ++i) {
res += dp[n][1][i][2];
res %= 1'000'000'007;
}
cout << res << '\n';
// srand(time({}));
// int n = 8;
// for (int i = 0; i < 100; ++i) {
// vector<int> heights;
// vector<bool> inHeights(1001, false);
// while (heights.size() < n) {
// int val = rand() % 20 + 1;
// if (inHeights[val]) continue;
// inHeights[val] = true;
// heights.push_back(val);
// }
// sort(heights.begin(), heights.end());
// cout << "Test " << i + 1 << ": \n";
// for (int &j : heights) cout << j << ' ';
// cout << '\n';
// for (int l = 0; l <= 100; l += rand() % 10 + 1) {
// cout << "l: " << l << '\n';
// int codeVal = code(n, l, heights);
// cout << "CodeVal: " << codeVal << '\n';
// int bruteforceVal = bruteforce(n, l, heights);
// cout << "BruteforceVal: " << bruteforceVal << '\n';
// if (codeVal != bruteforceVal) {
// cout << "Error\n";
// return 0;
// }
// }
// }
// vector<int> heights = {6, 7, 8, 9};
// cout << code(4, 4, heights) << '\n';
return 0;
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |