SRM 501 DIV1 500pt(DP)

时间:2021-04-28 04:53:31

题目简述

给定一个长度为n的序列,每个数值的范围为[-1,40],-1可以替换成0~40之间的数,要求你求出符合以下条件的序列有多少个?

1、每个数都是0~40之间的数

2、对于每一个数A[i],都需要小于等于前面所有数的算术平均值,及 对于 i, 1 <= i < N, 需要满足 A[i] <= (A[0] + A[1] + ... + A[i-1]) / i

3、序列中不存在三个连续的数刚好是严格递减的

题目做法

dp[i][j][k][f]表示当前第i个数和为j,第i-1个数为k,f表示i-2是否小于i-1的符合要求的序列总个数,时间复杂度为O(n^5)

代码:

 int dp[][][][];
class FoxAverageSequence
{
public:
int theCount(vector <int> seq)
{
memset(dp, , sizeof(dp));
int n = seq.size();
if (seq[] == -)
for (int i = ; i <= ; i++) dp[][i][i][] = ;
else dp[][seq[]][seq[]][] = ;
for (int i = ; i < n; i++)
for (int j = ; j <= ; j++)
for (int k = ; k <= ; k++)
for (int f = ; f < ; f++)
{
int num = seq[i];
if (dp[i - ][j][k][f])
{
int tj = j + num, tf = num < k ? : ;
if (num == -)
{
for (int a = ; a <= ; a++)
{
tf = a < k ? : ;
tj = j + a;
if (f && tf) continue;
if (a * i > j) break;
dp[i][tj][a][tf] += dp[i - ][j][k][f];
dp[i][tj][a][tf] %= MOD; } }
else
{
if (f && tf) continue;
if (num * i > j) continue;
dp[i][tj][num][tf] += dp[i - ][j][k][f];
dp[i][tj][num][tf] %= MOD;
}
}
}
int ans = ;
for (int i = ; i <= ; i++)
for (int j = ; j <= ; j++)
{
ans += dp[n - ][i][j][];
ans %= MOD;
ans += dp[n - ][i][j][];
ans %= MOD;
}
printf("%d\n",ans);
return ans; }
};