【JZOJ4806】打工

Description

这里写图片描述

Solution

不要看题目那么啰嗦,实际上一个合法序列的每个 ai 都要满足 aimax(a1,,ai1)+1

然后我们就可以开始“愉快”的dp了。

Fi,j 表示当前做到 i ,最大值为j

那么 Fi,j 可以从 Fi1,j1+Fi1,jj 转移过来,注意 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;
}
posted @ 2016-10-10 20:21  sadstone  阅读(28)  评论(0编辑  收藏  举报