Submission #1183741

#TimeUsernameProblemLanguageResultExecution timeMemory
1183741totoroSkyscraper (JOI16_skyscraper)C++20
100 / 100
363 ms243904 KiB
#include <algorithm> #include <iostream> #include <vector> const long long MOD = 1e9 + 7; inline long long add(long long a, long long b) { return ((a + b) % MOD + MOD) % MOD; } inline long long mul(long long a, long long b) { return (((a * b) % MOD) + MOD) % MOD; } inline void addto(long long& dest, long long x) { dest = add(dest, x); } int main() { int n, l; std::cin >> n >> l; std::vector<int> h(n); for (int& i : h) std::cin >> i; std::sort(h.begin(), h.end()); if (n == 1) { std::cout << "1\n"; return 0; } /* dp[i][comp][ends][k] is the number of ways to create `comp` components using `ends` ends, with total sum of EXACTLY `k` using first `i` shortest buildings Note that components are ORDERED, this just makes merging way easier dp[0][0][0][0] = 1 dp[0][!0][or !0][or !0] = 0 When inserting i, we can insert... ... As a new component (not an end), this can go into any of prev(`comp`+1-`ends`) = cur(`comp`-`ends`) locations It will increase the `k` value by (h[i] - h[i-1]) * prev((2*`comp` - `ends`)) ... As a new component (on an end), this can go into any of prev(2-`ends`) = cur(3-`ends`) locations. Note that cur(`ends`) cannot be 0 It will increase the `k` value by (h[i]-h[i-1]) * prev((2*`comp`-`ends`)) ... At the edge of an existing component (not on an end), this can be done in prev(2*`comp`-`ends`) ways It will increase the `k` value by (h[i]-h[i-1]) * prev(2*`comp`-`ends`) ... At the edge of an existing component (on an end), this can be done in prev(2-`ends`) ways It will increase the `k` value by (h[i]-h[i-1]) * prev(2*`comp`-`ends`) ... In between two components, to merge them. This can be done in prev(`comp`-1) ways It will increase the `k` value by (h[i]-h[i-1]) * prev(2*`comp`-`ends`) Note: we will proceed to do this using a forward dp, cus the logic is much simpler that way */ std::vector<std::vector<std::vector<std::vector<long long>>>> dp(n + 1, std::vector<std::vector<std::vector<long long>>>(n + 1, std::vector<std::vector<long long>>(3, std::vector<long long>(l + 1)))); dp[0][0][0][0] = 1; for (int i = 0; i < n; ++i) { int heightdiff = (i == 0 ? h[0] : h[i] - h[i - 1]); for (int comp = 0; comp <= n; ++comp) { for (int ends = 0; ends < 3; ++ends) { if (2 * comp - ends < 0) break; for (int k = 0; k <= l; ++k) { int newk = k + heightdiff * (2 * comp - ends); if (newk > l) continue; long long cur = dp[i][comp][ends][k]; if (comp + 1 <= n) { addto(dp[i + 1][comp + 1][ends][newk], mul(comp + 1 - ends, cur)); } if (comp + 1 <= n && ends < 2) { addto(dp[i + 1][comp + 1][ends + 1][newk], mul(2 - ends, cur)); } addto(dp[i + 1][comp][ends][newk], mul(2 * comp - ends, cur)); if (ends < 2) { addto(dp[i + 1][comp][ends + 1][newk], mul(2 - ends, cur)); } if (comp > 0) { addto(dp[i + 1][comp - 1][ends][newk], mul(comp - 1, cur)); } } } } } long long ans = 0; for (int k = 0; k <= l; ++k) { addto(ans, dp[n][1][2][k]); } std::cout << ans << '\n'; return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...