美丽数列

链接:https://ac.nowcoder.com/acm/problem/21313
来源:牛客网

题目描述

牛牛喜欢整数序列,他认为一个序列美丽的定义是
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的讨论,dp,平均数 思路: 二维dp[i][j] 表示第i个数是j的可能性的种数;但是平均数没法记录: dp[i[[j][k]表示第i个数是j并且前i个数之和平均数为k的种数; 没想到的点: flag 还要再加一个维度;平均数用sum代替比较好; dp[i][j][L][sum] 代码细节: dp也要是long long。。

 

#include<bits/stdc++.h>
using namespace std;

long long dp[45][45][3][1605];
const int mod= 1e9+7;
int  a[43];
int main(){
    int n;
    cin >> n;
    
    for(int i = 1; i <= n; i++)
        cin >> a[i];
    memset(dp,0,sizeof(dp));
    //初始化
    if (a[1] == -1)
        for(int j = 0; j <= 40; j++)   dp[1][j][1][j] = 1;
    else    dp[1][a[1]][1][a[1]] = 1;
     
    for(int i = 2; i <= N; i++)
        if(a[i] == -1){// j 0-40
            for(int j = 0; j <=40; j++)//枚举当前可能的数 0~40
                for(int k = 0; k <= 40; k++){//枚举当前前一个(i-1)可能的数 0~40
                    for(int sum = j*(i-1); sum<=1600-j; sum++)//枚举前(i-1)个满足条件的和sum;
                        if(j >= k){// 当前的数大于之前的数,有两种情况
                            dp[i][j][1][sum+j] += dp[i-1][k][1][sum] + dp[i-1][k][2][sum];
                            dp[i][j][1][sum+j] %= mod;
                        }else//当前的数小于之前的数,只有一种情况。
                        {
                            dp[i][j][2][sum+j] += dp[i-1][k][1][sum];
                            dp[i][j][2][sum+j] %= mod;
                        }                       
                }
        }
        else
        {
            int j = a[i];// j只能取a[i]
            for(int k = 0; k <= 40; k++){
                    for(int sum = j*(i-1); sum<=1600-j; sum++)
                        if(j >= k){
                            dp[i][j][1][sum+j] += dp[i-1][k][1][sum] + dp[i-1][k][2][sum];
                            dp[i][j][1][sum+j] %= mod;
                        }else
                        {
                            dp[i][j][2][sum+j] += dp[i-1][k][1][sum];
                            dp[i][j][2][sum+j] %= mod;
                        }
                        
                }
        }
     
   long long ans = 0;
    for(int j = 0; j <= 40; j++){//最后一个数可能的值
        for(int sum = j*n;sum <= 1600; sum++){//枚举可能的和
            ans += dp[n][j][1][sum] + dp[n][j][2][sum];
            ans %= mod;
        }
    }
  
   cout << ans << endl;
    system("pause"); 
    
}

 

参考:

https://www.twblogs.net/a/5d494e75bd9eee5327fbc02d/zh-cn
https://ac.nowcoder.com/acm/problem/blogs/21313

 

 

posted @ 2019-11-28 23:09  swiftAlien  阅读(385)  评论(0编辑  收藏  举报