The grass has dried up in Farmer John's pasture due to a drought. After hours of despair and contemplation, FJ comes up with the brilliant idea of purchasing corn to feed his precious cows.
FJ’s?NN?(1≤N≤1001≤N≤100) cows are arranged in a line such that the?iith cow in line has a non-negative integer hunger level of?hihi. As FJ’s cows are social animals and insist on eating together, the only way FJ can decrease the hunger levels of his cows is to select two adjacent cows?ii?and?i+1i+1?and feed each of them a bag of corn, causing each of their hunger levels to decrease by one.
FJ wants to feed his cows until all of them have the same non-negative hunger level. Although he doesn't know his cows' exact hunger levels, he does know an upper bound on the hunger level of each cow; specifically, the hunger level?hihi?of the?ii-th cow is at most?HiHi?(0≤Hi≤10000≤Hi≤1000).
Your job is to count the number of?NN-tuples of hunger levels?[h1,h2,…,hN][h1,h2,…,hN]?that are consistent with these upper bounds such that it is possible for FJ to achieve his goal, modulo?109+7109+7.
The first line contains?NN.The second line contains?H1,H2,…,HNH1,H2,…,HN.
The number of?NN-tuples of hunger levels modulo?109+7109+7.
3 9 11 7
241
There are?(9+1)?(11+1)?(7+1)(9+1)?(11+1)?(7+1)?33-tuples?hh?that are consistent with?HH.
One of these tuples is?h=[8,10,5]h=[8,10,5]. In this case, it is possible to make all cows have equal hunger values: give two bags of corn to both cows?22?and?33, then give five bags of corn to both cows?11?and?22, resulting in each cow having a hunger level of?33.
Another one of these tuples is?h=[0,1,0]h=[0,1,0]. In this case, it is impossible to make the hunger levels of the cows equal.
4 6 8 5 9
137
NN?is even in even-numbered tests and odd in odd-numbered tests.
Problem credits: Arpan Banerjee and Benjamin Qi
[/hide]
(Analysis by Andi Qu, Arpan Banerjee, Benjamin Qi)
Case 1:?NN?is even
Note that if some starting?NN-tuple can make all cows end up with hunger level?xx, then it can also make all cows end up with hunger level?00?(by feeding each consecutive pair of cows?xx?bags of corn). So it suffices to find the number of?NN-tuples that can be converted to all?00's.
If we want to check whether a specific?NN-tuple can be converted to all?00's, then the following pseudocode suffices:
for (i in 2..N) {
h[i] -= h[i-1]
assert(h[i] >= 0)
}
assert(h[N] == 0)
The reasoning behind this is that if?h1,…,hi?2h1,…,hi?2?are all equal to zero already, then the only way to make?hi?1=0hi?1=0?is by feeding?hi?1hi?1?bags of corn to each of cows?i?1i?1?and?ii.
Motivated by this, we can define a DP array where?dp[i][j]dp[i][j]?is the number of ways to choose?h1…hih1…h(huán)i?satisfying?hk≤Hkhk≤Hk?for all?1≤k≤i1≤k≤i?such that after the?ii-th iteration of the loop in the pseudocode above,?hi=jhi=j. Then
That is, if?hi?1=xhi?1=x?and?hi=j+x≤Hihi=j+x≤Hi?before the?ii-th iteration of the loop, then?hi?1=0hi?1=0?and?hi=jhi=j?after the?ii-th iteration of the loop. The final answer will be?dp[N][0]dp[N][0].
A straightforward implementation of this algorithm runs in?O(N(maxH)2)O(N(maxH)2)?time, which is already fast enough. However, we can speed this up by using prefix sums for the transition since we are summing over a contiguous range. Specifically, define?pref[i][j]=∑jx=0dp[i][x]pref[i][j]=∑x=0jdp[i][x]; then?dp[i][j]=pref[i?1][Hi?j]dp[i][j]=pref[i?1][Hi?j]. This results in a runtime of?O(N(maxH))O(N(maxH)).
Andi's code:
#include <iostream>
#include <algorithm>
#include <cstring>
typedef long long ll;
using namespace std;
const ll MOD = 1e9 + 7;
int main() {
cin.tie(0)->sync_with_stdio(0);
int n, h[101];
cin >> n;
for (int i = 1; i <= n; i++) cin >> h[i];
ll dp[1001], pref[1001];
for (int i = 0; i <= h[1]; i++) pref[i] = i + 1;
for (int i = h[1] + 1; i <= 1000; i++) pref[i] = h[1] + 1;
for (int i = 2; i <= n; i++) {
memset(dp, 0, sizeof dp);
for (int j = 0; j <= h[i]; j++) {
dp[j] = pref[h[i] - j];
if (dp[j] >= MOD) dp[j] -= MOD;
}
for (int j = 0; j <= 1000; j++) {
pref[j] = dp[j];
if (j) pref[j] += pref[j - 1];
if (pref[j] >= MOD) pref[j] -= MOD;
}
}
cout << pref[0];
return 0;
}
Case 2:?NN?is odd
In this case, it is?not?true that if a starting?NN-tuple can make all cows end up with hunger level?xx, then it can also make all cows end up with hunger level?00. In fact, if a starting?NN-tuple can make all cows end up with hunger level?xx, then?xx?must be unique (as mentioned in the Bronze analysis). So it suffices to sum the number of starting?NN-tuples over all final hunger levels?xx?satisfying?0≤x≤minH0≤x≤minH.
To count this quantity for a fixed?xx, consider subtracting?xx?from all?hihi?and?HiHi. Then the problem reduces to converting tuples to all?00's, which was described above.
The final time complexity for this case is?maxHmaxH?times that of the complexity for the previous case, or?O(N(maxH)2)O(N(maxH)2).
Andi's code:
#include <iostream>
#include <algorithm>
#include <cstring>
typedef long long ll;
using namespace std;
const ll MOD = 1e9 + 7;
int main() {
cin.tie(0)->sync_with_stdio(0);
int n, h[101];
cin >> n;
for (int i = 1; i <= n; i++) cin >> h[i];
int mn = *min_element(h + 1, h + n + 1);
ll dp[1001], pref[1001], ans = 0;
do {
// on x-th iteration of loop, count number of tuples
// that can make all heights equal to x-1
for (int i = 0; i <= h[1]; i++) pref[i] = i + 1;
for (int i = h[1] + 1; i <= 1000; i++) pref[i] = h[1] + 1;
for (int i = 2; i <= n; i++) {
memset(dp, 0, sizeof dp);
for (int j = 0; j <= h[i]; j++) {
dp[j] = pref[h[i] - j];
if (dp[j] >= MOD) dp[j] -= MOD;
}
for (int j = 0; j <= 1000; j++) {
pref[j] = dp[j];
if (j) pref[j] += pref[j - 1];
if (pref[j] >= MOD) pref[j] -= MOD;
}
}
ans += pref[0];
if (ans >= MOD) ans -= MOD;
for (int i = 1; i <= n; i++) h[i]--;
} while (n % 2 && mn--);
cout << ans;
return 0;
}
Interestingly, each DP transition is equivalent to reversing a subarray of the previous prefix sum array, so we can code a very short (and fast) solution using functions from C++'s standard library.
#include <algorithm>
#include <cstdio>
#include <numeric>
using namespace std;
int mod_add(int x, int y) {
int res = x + y;
if (res >= 1000000007) res -= 1000000007;
return res;
}
int main() {
int n, h[101], mn, mx, dp[1001], ans = 0;
scanf("%d", &n);
for (int i = 0; i < n; i++) scanf("%d", h + i);
mn = *min_element(h, h + n), mx = *max_element(h, h + n);
do {
fill(dp, dp + mx + 1, 1);
for (int i = 0; i < n; i++) {
reverse(dp, dp + h[i] + 1);
fill(dp + h[i] + 1, dp + mx + 1, 0);
partial_sum(dp, dp + mx + 1, dp, mod_add);
}
ans = mod_add(ans, dp[0]);
for (int i = 0; i < n; i++) h[i]--;
} while (n % 2 && mn-- && mx--);
printf("%d\n", ans);
return 0;
}
[/hide]

? 2025. All Rights Reserved. 滬ICP備2023009024號(hào)-1