A Grouping Problem#1525

A Grouping Problem (Editorial)

Let a_1, a_2, ..., a_n be a given set of integers. Denote by F_{ik}~(i \ge k) the sum of all possible products of integers chosen from the first integers a_1, ..., a_i. Let us construct the following table of F_{ik} values:

For four numbers, we obtain:

The following recurrence relations hold:

F_{i1} = F_{(i-1)1} + a_i\\ F_{ii} = F_{(i-1) (i-1)} \cdot a_i, 1 \le i \le n \\ F_{ik} = F_{(i-1)k} + F_{(i-1) (k-1)} \cdot a_i, 1 \le i \le n, 1 < k < i

For example,

The values of each subsequent row are computed based on the values of the previous row, so it is sufficient to store a single linear array of size up to . The recalculation of the -th row should be performed from the end: first compute F_{ii}, then F_{i(i-1)}, and so on down to F_{i1}. All computations must be performed modulo .

Example

Consider the first test case. We'll construct two tables: in the first table, computations are performed without the modulo, and in the second table, computations are performed modulo m = 10.

For example,

The answer is the maximum value in the fourth row of the second table.

Algorithm implementation

Declare a linear array , where the values of F_{ik} will be recomputed.

long long d[1000];

Read the number of elements and the value . For each input test case, the array is initially cleared. The first number a_1 is stored in .

while (scanf("%lld %lld",&n,&m), n + m > 0)
{
  memset(d,0,sizeof(d));
  scanf("%lld",&d[0]);

Next, read the value x = a_{i+1}~(1 \le i < n) and recalculate the values of F_{ik} for k = i, i - 1, ..., 1 using the recurrence formulas given above. All computations are performed modulo .

  for (i = 1; i < n; i++)
  {
    scanf("%lld",&x);
    d[i] = (d[i-1] * x) % m; 

    for (j = i - 1; j > 0; j--)
      d[j] = (d[j-1] * x + d[j]) % m;

    d[0] = (d[0] + x) % m;
  }

Find the maximum value among the elements of the array and store it in the variable .

  res = 0;
  for (i = 0; i < n; i++)	   
    if (d[i] > res) res = d[i];

Print the answer.

  printf("%lld\n",res);
}