SRM 501 DIV1 500pt(DP)

题目简述

给定一个长度为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)

代码:

 1 int dp[45][2000][45][2];

 2 class FoxAverageSequence

 3 {

 4 public:

 5     int theCount(vector <int> seq)

 6     {

 7         memset(dp, 0, sizeof(dp));

 8         int n = seq.size();

 9         if (seq[0] == -1)

10             for (int i = 0; i <= 40; i++) dp[0][i][i][0] = 1;

11         else dp[0][seq[0]][seq[0]][0] = 1;

12         for (int i = 1; i < n; i++)

13             for (int j = 0; j <= 1600; j++)

14                 for (int k = 0; k <= 40; k++)

15                     for (int f = 0; f < 2; f++)

16                     {

17                         int num = seq[i];

18                         if (dp[i - 1][j][k][f])

19                         {

20                             int tj = j + num, tf = num < k ? 1 : 0;

21                             if (num == -1)

22                             {

23                                 for (int a = 0; a <= 40; a++)

24                                 {

25                                     tf = a < k ? 1 : 0;

26                                     tj = j + a;

27                                     if (f && tf) continue;

28                                     if (a * i > j) break;

29                                     dp[i][tj][a][tf] += dp[i - 1][j][k][f];

30                                     dp[i][tj][a][tf] %= MOD;

31 

32                                 }

33 

34                             }

35                             else

36                             {

37                                 if (f && tf) continue;

38                                 if (num * i > j) continue;

39                                 dp[i][tj][num][tf] += dp[i - 1][j][k][f];

40                                 dp[i][tj][num][tf] %= MOD;

41                             }

42                         }

43                     }

44         int ans = 0;

45         for (int i = 0; i <= 1600; i++)

46             for (int j = 0; j <= 40; j++)

47             {

48                 ans += dp[n - 1][i][j][0];

49                 ans %= MOD;

50                 ans += dp[n - 1][i][j][1];

51                 ans %= MOD;

52             }

53             printf("%d\n",ans);

54         return ans;

55 

56     }

57 };

 

你可能感兴趣的:(div)