//URL:https://www.luogu.com.cn/problem/P4798
/*
一场卡尔文球比赛会有 nn 名选手参与,他们的编号分别为 1…n1…n,分为若干个非空的球队。我们规定球队之间按照每个球队编号最小的选手的编号排序,并且以从 1 开始的连续整数编号。
举个栗子,譬如 1 号选手自己成一队,2, 3 和 5 号选手成一队,4 和 6 号选手成一队。
> 1 1
> 2 3 5 2 3 5
> 4 6 4 6
那么 1 号选手的球队就是 1 号球队,2 号选手的球队就是 2 号球队,4 号选手的球队就是 3 号球队。
> 1|1 1|1
> 2|2 3 5 2|2 3 5
> 3|4 6 3|4 6
每个人每天会选择不同的球队,我们可以在记录时省略选手的编号,仅记录每个位置对应选手所属球队编号的序列(上述例子为 1 2 2 3 2 3),因为每天的选手是一样的。当可能的选择方案全部被使用过后,锦标赛就结束了。
由于选择方案十分多,选择困难症患者纷纷表示力不从心。今年,我们决定根据记录的序列的字典序来选择方案。因此,第一天,所有人都在一个队 1 1 1 1 1;第二天,所有人都与 6 号针锋相对 1 1 1 1 1 2……在最后一天,所有人互相打响战争 1 2 3 4 5 6。
对于给定的球队记录,请你算出将会在未来的哪一天使用该记录。输出这个数字对 1 000 0071 000 007 取余的结果。
这道题是求给定数列的排名,也就是比给定数列字典序小的合法序列方案数+1
因为给出的序列max_num<=n-> dp[i][j][lim] 前i位 最大数j 等于/小于原序列(lim==1/0) 的总数
dp[i+1][j][0]+=dp[i][j][1]*(a[i+1]-1)+dp[i][j][0]*j
dp[i+1][j+1][0]+=dp[i][j][0]
(a[i+1]==j+1)dp[i+1][j+1][1]+=dp[i][j][1]
dp[i+1][j][1]+=dp[i][j][1]
*/
/*
3
1 2 2
4
*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<string.h>
#include<queue>
#include<vector>
#include<bits/stdc++.h>
typedef long long ll;
#define ddd printf("-----------------------\n");
using namespace std;
const int maxn=1e1 +10;
const int mod=1e6+7;
const int inf=0x3f3f3f3f;
int n,a[10010];
ll dp[2][10010][2],ans;
int main()
{
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
dp[1][1][1]=1;
for(int i=1;i<n;i++){
for(int j=1;j<=i;j++)
{
/*
dp[i&1][j][0]%=mod,dp[i&1][j][1]%=mod;
dp[i&1^1][j][0]+=dp[i&1][j][1]*(a[i+1]-1)+dp[i&1][j][0]*j;
dp[i&1^1][j+1][0]+=dp[i&1][j][0];
(a[i+1]==j+1? dp[i&1^1][j+1][1]:dp[i&1^1][j][1])+=dp[i&1][j][1];
dp[i&1][j][0]=dp[i&1][j][1]=0;
*/
dp[i%2][j][0]%=mod,dp[i%2][j][1]%=mod;
dp[(i+1)%2][j][0]+=dp[i%2][j][1]*(a[i+1]-1)+dp[i%2][j][0]*j;
dp[(i+1)%2][j+1][0]+=dp[i%2][j][0];
(a[i+1]==j+1? dp[(i+1)%2][j+1][1]:dp[(i+1)%2][j][1])+=dp[i%2][j][1];
dp[i%2][j][0]=dp[i%2][j][1]=0;
}
}
for(int i=n,j=1;j<=n;j++) ans=(ans+dp[i%2][j][0]%mod)%mod;
cout<<ans+1<<'\n';
return 0;
}