Peter has a sequence of IntegersA1 ,?A2 ,?...,?AN. Peter wants all numbers in the sequence to equalH. He can perform the operation of "adding one on the segment [L,?R] ": Add one to all elements of the sequence with indices fromLToR(Aggressive ). at that, Peter never chooses any element as the beginning of the segment twice. similarly, Peter never chooses any element as the end of the segment twice. in other words, for any two segments [L1 ,?R1] and [L2 ,?R2], where Peter added one, the following inequalities hold:L1? ?L2 andR1? ?R2.
How many distinct ways are there to make all numbers in the sequence equalH? Print this number of ways modulo 1000000007 (109? +? 7). Two ways are considered distinct if one of them has a segment that isn't in the other way.
Input
The first line contains two integersN,?H(1? ≤?N,?H? ≤? (2000). The next line containsNIntegersA1 ,?A2 ,?...,?AN(0? ≤?AI? ≤? 2000 ).
Output
Print a single integer-the answer to the problem modulo 1000000007 (109? +? 7 ).
Sample test (s) Input
3 21 1 1
Output
4
Input
5 11 1 1 1 1
Output
1
Input
4 33 2 1 1
Output
0: select several non-repeating intervals to execute the + 1 operation. How many methods can be used to make the sequence M-wise: DP [I] [open] indicates the number of unmatched right brackets on the left side after the I, and a good question: reference; reference:Lets use dynamic programming to solve this problem.DP[I] [Opened]-The number of ways to cover prefix of array 1. I by segments and make it equalHAnd remain afterI-Th ElementOpenedSegments that are not closed.
Consider all possible variants opening/closing segments in each position :-]Closing one segment-[Opening one new segment-[]Adding one segment with length 1-][Closing one opened segment and opening a new one--Do nothing
Lets understand how to build dynamic. It is obviusly to understand thatA[I]? +?OpenedCan be equalHOrH? -? 1. Otherwise, number of such ways equals 0.
Consider this two cases separately:
1)A[I]? +?Opened? =?HIt means that number of opened segments afterI-Th as Max as possible and we can't open one more segment in this place. So there are two variants :-[Opening a new segment. If onlyOpened?>? 0.dp[i][opened] += dp[i-1][opened + 1]--Do nothing.dp[i][opened] += dp[i-1][opened]
Other variants are impossible because of summary valueA[I] Will be greaterH(When segment is finishing in current position-it increase value, but do not influence onOpened, By the dynamic definition.
2)A[I]? +?Opened? +? 1? =?HHere we consider ways whereI-Th element has been increasedOpened? +? 1 segments, but afterI-Th remain onlyOpenedNot closed segments. Therefore, there are next variants :-]-Closing one of the opened segments (we can do itOpened? +? 1 ways ).dp[i][opened] += dp[i-1][opened + 1] * (opened + 1)-[]-Creating 1-length segment.dp[i][opened] += dp[i-1][opened]-][-If onlyOpened?>? 0. Amount of ways to choose segment which we will close equalsOpened.dp[i][opened] += dp[i-1][opened] * opened
Start values-dp[1][0] = (a[1] == h || a[1] + 1 == h?1:0); dp[1][1] = (a[1] + 1 == h?1:0)
Answer-dp[n][0].
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>typedef long long ll;using namespace std;const int maxn = 2010;#define mod 1000000007ll dp[maxn][maxn];int a[maxn];inline void add(ll &a, ll b) {a += b;a %= mod;}int main() {int n, h;cin >> n >> h;for (int i = 1; i <= n; i++)cin >> a[i];dp[1][0] = (a[1] == h || a[1]+1 == h ? 1 : 0);dp[1][1] = (a[1]+1 == h ? 1 : 0);for (int i = 2; i <= n+1; i++)for (int open = max(0, h-a[i]-1); open <= min(h-a[i], i); open++) {if (open + a[i] == h) {add(dp[i][open], dp[i-1][open]);if (open > 0)add(dp[i][open], dp[i-1][open-1]);}if (open + a[i] + 1 == h) {add(dp[i][open], dp[i-1][open+1]*(open+1));add(dp[i][open], dp[i-1][open]);add(dp[i][open], dp[i-1][open]*open);}}cout << dp[n][0] << endl;return 0;}
Codeforces round #266 (Div. 2) D. Increase Sequence