链接:https://ac.nowcoder.com/acm/problem/21313


时间限制:C/C++ 1秒,其他语言2秒

空间限制:C/C++ 524288K,其他语言1048576K

64bit IO Format: %lld

题目描述

牛牛喜欢整数序列,他认为一个序列美丽的定义是

1:每个数都在0到40之间

2:每个数都小于等于之前的数的平均值

具体地说:for each i, 1 <= i < N,  A[i] <= (A[0] + A[1] + ... + A[i-1]) / i.

3:没有三个连续的递减的数


现在给你一个序列,每个元素是-1到40,你可以将序列中的-1修改成任意的数,求你可以得到多少个美丽序列,答案对1e9+7取模


输入描述:

第一行输入一个整数n (1 ≤ n ≤ 40)

第二行输入n个整数

输出描述:

输出一个整数

示例1

输入

复制

2
3 -1

输出

复制

4

示例2

输入

复制

3
5 3 -1

输出

复制

2

示例3

输入

复制

3
-1 0 40

输出

复制

0

示例4

输入

复制

11
-1 40 -1 -1 -1 10 -1 -1 -1 21 -1

输出

复制

579347890

备注:

子任务1: n <= 10
子任务2: n <= 20
子任务3: 无限制


这个题涉及了很多常规的dp操作,挺不错的一道题​美丽序列(动态规划入门级别)_c++

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define per(i,a,b) for(int i=a;i>=(b);--i)
#define in(x) scanf("%d",&x)
#define ind(x) scanf("%lld",&x)
#define out(x) printf("%d ",x);
#define outln(x) printf("%lld\n",x);
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
#define PE(x,y) x=((x)+(y))%mod
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
ll powmod(ll a,ll b) {ll res=1;a%=mod;
for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
const int N=44;
int dp[N][N][5][1700];
int a[N],t,n;
int main()
{
in(n);
rep(i,1,n) in(a[i]);

if(a[1]!=-1) dp[1][a[1]][1][a[1]]=1;
else rep(i,0,40) dp[1][i][1][i]=1;

rep(i,2,n){
if(a[i]!=-1){
rep(sum,(i-1)*a[i],1600-a[i]){
int newsum=sum+a[i];
rep(last,0,40){
if(a[i]<last) PE(dp[i][a[i]][2][newsum],dp[i-1][last][1][sum]);
else{
PE(dp[i][a[i]][1][newsum],dp[i-1][last][2][sum]);
PE(dp[i][a[i]][1][newsum],dp[i-1][last][1][sum]);
}
}
}
}
else{
rep(newlast,0,40){
rep(sum,(i-1)*newlast,1600-newlast){
int newsum=sum+newlast;
rep(last,0,40){
if(newlast<last){
PE(dp[i][newlast][2][newsum],dp[i-1][last][1][sum]);
}
else{
PE(dp[i][newlast][1][newsum],dp[i-1][last][2][sum]);
PE(dp[i][newlast][1][newsum],dp[i-1][last][1][sum]);
}
}
}
}
}
}
ll ans=0;
rep(last,0,40)
rep(len,1,2)
rep(sum,0,1600)
PE(ans,dp[n][last][len][sum]);
outln(ans);
}