【JZOJ4806】打工
Description
Solution
不要看题目那么啰嗦,实际上一个合法序列的每个 ai 都要满足 ai≤max(a1,⋯,ai−1)+1 。
然后我们就可以开始“愉快”的dp了。
设
Fi,j
表示当前做到
i
,最大值为
那么 Fi,j 可以从 Fi−1,j−1+Fi−1,j∗j 转移过来,注意 ai 的边界即可。
Code
打的是很慢的方法,不同上面的。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
#define N 10001
#define mo 1000007
#define ll long long
using namespace std;
ll f[2][N][2];
int a[N];
int n;
int main()
{
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
cin>>n;
fo(i,1,n) scanf("%d",&a[i]);
f[1][1][1]=1;
int p=1,q=a[1];
fo(i,2,n)
{
p=1-p;
q=max(q,a[i]);
fo(j,1,i)
{
f[p][j][1]=0;
f[p][j][0]=(f[1-p][j][0]*max(0,j-a[i]+1)+(f[1-p][j][0]+f[1-p][j][1])*min(j,a[i]-1)+f[1-p][j-1][0])%mo;
if(j<a[i]) f[p][j][0]=f[p][j][0]+f[1-p][j-1][1];
}
f[p][q][1]=1;
}
ll ans=0;
fo(i,1,n) ans=(ans+f[p][i][0]+f[p][i][1])%mo;
cout<<ans;
}