题意:
牛牛喜欢整数序列,他认为一个序列美丽的定义是
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取模.
对于题目我们很容易想到第一维是到了第几个数.对于第二个条件,我们就得想到前面的总和是多少,到了第三个条件我们就得设当前是递减序列的第几个,为了方便转移我们还需要另设一个就是当前的值是多少.总体而言dp的状态就是dp[i][j][l][k],表示到了第i个数值是j位于递减序列中的第l个总和为k的数列有多少.那么代码就很容易了.
代码如下:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=45,M=1605,L=3;
const ll mod=1e9+7;
ll a[N];
ll dp[N][N][L][M];
int main()
{
ll n;
scanf("%lld",&n);
for(ll i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
}
if(a[1]==-1)
{
for(ll i=0;i<=40;i++) dp[1][i][1][i]=1;
}
else dp[1][a[1]][1][a[1]]=1;
for(ll i=2;i<=n;i++)//到了第几个.
{
if(a[i]==-1)//不确定.
{
for(ll j=0;j<=40;j++)//枚举当前哪个数.
{
for(ll lj=0;lj<=40;lj++)//枚举上个数是哪个数.
{
for(ll k=j*(i-1);k<=1600-j;k++)//枚举可行的sum
{
if(j>=lj)//假设我当前值大于上一个的值.
{
dp[i][j][1][k+j]=(dp[i][j][1][k+j]+dp[i-1][lj][1][k]+dp[i-1][lj][2][k])%mod;
}
else
{
dp[i][j][2][k+j]=(dp[i][j][2][k+j]+dp[i-1][lj][1][k])%mod;
}
}
}
}
}
else//确定.
{
for(ll lj=0;lj<=40;lj++)//枚举上个数是哪个数.
{
for(ll k=a[i]*(i-1);k<=1600-a[i];k++)//枚举可行的sum
{
if(a[i]>=lj)//假设我当前值大于上一个的值.
{
dp[i][a[i]][1][k+a[i]]=(dp[i][a[i]][1][k+a[i]]+dp[i-1][lj][1][k]+dp[i-1][lj][2][k])%mod;
}
else
{
dp[i][a[i]][2][k+a[i]]=(dp[i][a[i]][2][k+a[i]]+dp[i-1][lj][1][k])%mod;
}
}
}
}
}
ll ans=0;
for(ll j=0;j<=1600;j++)
{
for(ll i=0;i<=40;i++)
{
ans=(ans+dp[n][i][1][j])%mod;
ans=(ans+dp[n][i][2][j])%mod;
}
}
printf("%lld\n",ans);
return 0;
}
京公网安备 11010502036488号