打工

这里写图片描述
Input
第一行,一个整数N表示参赛人数。
第二行,N个整数,表示询问的分队方式的序列。
Output
一行,一个整数表示这种方式会在第几天被采用。答案对1,000,007取模。
Sample Input
3
1 2 2
Sample Output
4
Data Constraint
对于100%的数据,N ≤ 10000 , 数据保证询问的数列是一个有效的序列。

Hint
比赛各天的分队情况如下:
第一天:1,1,1
第二天:1,1,2
第三天:1,2,1
第四天:1,2,2
第五天:1,2,3

The Solution

首先注意到一个简单的性质,
一个数 x 要出现在序列里,必须要
在它前面的位置出现 x-1。

可以注意到,一个序列中如果要出现 k 这个数,那么在他之前的
位置 1~k-1 必定都出现过,这样构造出的序列才是合法的。

举个例子 1,2,2,2….3….1,2,1,2….3

然后我们可以设f[i][j][0..1]表示前i个数,最大的数是j,
0表示 < j这个数,1表示 = 这个数。

普通转移很显然,f[i]只与f[i-1],f[i]只与f[i+1]有关,所以我们可以用滚动数组。

从后往前,考虑每一个位置,与原序列完全符合,或字典序比原序列小
那么方案数显然是
f[i+1][max(x,j)][z]=((ll)f[i+1][max(x,j)][z]+f[i][j][l])
z表示滚动0..1

计算方案数的式子长度为i,
写出来类似 1jj.....1(j+1)(j+1)....1(j+2)(j+2)

这条式子很明显

因为你放一个数设为k,那么前面就有1~k的那么多个位置,再放入小于k的数的方案数显然为上述式子。

考虑 f[i]如何由 f[i-1]推来。当前这一位的后一位放 k 那么当前这
位就有 k 种放法;后一位放 k+1,就只有一种放法。

可以枚举最大值k

时间复杂度:O(N^2)

CODE

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define fo(i,a,b) for (int i=a;i<=b;i++)
#define N 10005
#define mo 1000007

using namespace std;

int n,a[N];
int f[2][N][2],ans=0;// qian i ge shu zui da de shu shi j
//0 < 1 =

typedef long long ll;

int main()
{
    freopen("data.in","r",stdin);
    scanf("%d",&n);
    fo(i,1,n) scanf("%d",&a[i]);
    f[0][1][1] = 1;
    int p=0,q=1;//o u
    int mx = 1;
    fo(i,1,n)
    {
        q = 1 - p;
        mx = max(mx,a[i]);
        fo(j,1,i)
        {
            f[q][j][1] = 0;
            int tmp = max(0,j-a[i]+1) , t = min(j,a[i]-1);
            f[q][j][0] =(f[p][j][0] * (ll)tmp + (f[p][j][0]+f[p][j][1]) * (ll)t + f[p][j-1][0]) % mo;
            if (j < a[i]) f[q][j][0] += f[p][j-1][1];
        }   
        f[q][mx][1] = 1;
        p = q;
    }
    fo(i,1,n) ans = ((ll)ans + f[p][i][1] + f[p][i][0])%mo;
    printf("%d\n",ans);
    return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值