链接: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取模
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