description

analysis
-
DPDPDP
-
易知一个数xxx若想出现,则它前面[1,x−1][1,x-1][1,x−1]每一个数都要出现过,否则这种情况会被顶替
-
则设f[i][j]f[i][j]f[i][j]表示还有iii个空位、前面已经填过的数最大为jjj的方案数
-
就是说f[i][j]f[i][j]f[i][j]状态可以由填jjj个数的j∗f[i−1][j]j*f[i-1][j]j∗f[i−1][j]或填j+1j+1j+1的f[i−1][j+1]f[i-1][j+1]f[i−1][j+1]转移得到
-
最终答案就是∑(a[i]−1)f[n−i][max(a[1...n−1])]\sum(a[i]-1)f[n-i][max(a[1...n-1])]∑(a[i]−1)f[n−i][max(a[1...n−1])]
code
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define MAXN 10005
#define mod 1000007
#define ll int
#define fo(i,a,b) for (ll i=a;i<=b;++i)
#define fd(i,a,b) for (ll i=a;i>=b;--i)
using namespace std;
ll f[MAXN][MAXN];
ll a[MAXN],mx[MAXN];
ll n,ans;
inline ll read()
{
ll x=0,f=1;char ch=getchar();
while (ch<'0' || '9'<ch){if (ch=='-')f=-1;ch=getchar();}
while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
inline ll max(ll x,ll y){return x>y?x:y;}
int main()
{
freopen("T1.in","r",stdin);
n=read(),f[0][0]=1;
fo(i,1,n)mx[i]=max(mx[i-1],a[i]=read()),f[0][i]=1;
fo(i,1,n)
{
fo(j,1,n)
f[i][j]=((long long)f[i-1][j]*j%mod+f[i-1][j+1])%mod;
}
fo(i,1,n)ans=(ans+(long long)(a[i]-1)*f[n-i][mx[i-1]])%mod;
printf("%d\n",(ans+1)%mod);
return 0;
}

3454

被折叠的 条评论
为什么被折叠?



