n = 5x+2y+z

Seeking n = 5x + 2y + z All negative integer solution non e.g. n = 5, the 4 Solution: (0, 0, 5), (0, 1, 3), (0, 2, 1), (1, 0, 0).

1. The most common solution, three loop through:

int SolutionLoop(int n) {
  int x = n / 5;
  int y = n / 2;
  int z = n;
  int res = 0;
  for (int i = 0; i <= x; i++) {
    for (int j = 0; j <= y; j++) {
      for (int k = 0; k <= z; k++) {
        if (n == 5*i + 2*j + k) res++;
      }
    }
  }
  return res;
}

Optimization 1: unroll 3rd loop (loop expansion innermost layer)

Replace
for (int k = 0; k <= z; k++) {
  if (n == 5*i + 2*j + k) res++;
}
by the following:
if (n - 5*i - 2*j >= 0) res++;

Optimization 2: remove if (if removal determination)

Replace
for (int j = 0; j <= y; j++) {
  if (n - 5*i - 2*j >= 0) res++;
}
by the following:
for (int j = 0; j <= (n - 5*i) / 2; j++) {
  res++;
}

Optimization 3: unroll second loop (second layer to expand cycle)

step 3 : unroll 2nd loop
Replace
for (int j = 0; j <= (n - 5*i) / 2; j++) {
  res++;
}
by the following:
res += (n - 5*i) / 2 + 1;

At this point it has been removed into a code two cycles as follows:

int unrollLoop(int n) {
  int x = n / 5;
  int res = 0;
  for (int i = 0; i <= x; i++) {
    res += (n - 5*i) / 2 + 1;
  }
  return res;
}

So how to start the final layer of the cycle it?

It can be seen: the cycle corresponds to the formula x:

According to the arithmetic sequence summation formula: you can easily find the results:

 

If you write code, according to this formula natural speed is the fastest, but if n = 100, you find the correct result is 541, but calculated using the above formula is 546, and that the difference in the end result where is it?

 If the calculated number is too large reason 7/2 * 6 sequentially calculated result is 18, but if out of sequence * 7 6/2, then the result is 21, it is calculated by the above equation is:: For example the the accuracy of this loss is added to the list given, as the original, there is a summation formula divided by 2, if (n-5i) is even, then there is no problem, but if the (n-5i) is the base, can not be free of reorder the example: 7/2 + 5/2 = 5, but the (5 + 7) / 2 = 6, it has been partially loses precision every 1/2, but because of the adjustment of the calculation procedure leads to results too large.

Know the cause of the problem, then it is a good solution, just like a separate count in accordance with an even number of the base. The (n-5i) is divided into a set of odd, even-numbered division but to a set of arbitrary n, n-5i parity is not set, the parity of the two types according to the case where n:

1) n is an odd number:

  ① when i is odd, n-5i is an even number, (n-5i) / 2 without loss of precision

  ② when i is an even number n-5i as the base, then the (n-5i) / 2, will be converted to (n-5i-1) / 2

2) n is even:

  ① when i is odd, n-5i is odd

  ② when i is an even number is an even number n-5i

Optimization: Expand the last layer loop:

int unrollAllLoop(int n) {
  int res = 0;
  int even = n / 10 + 1;
  int odd = n / 5 + 1 - even;
  if (n % 2) {
    //res +=  (n - 1 + n - (2*even - 2)*5) / 2 * even / 2;
    res += (n + 4 - 5*even) * even / 2;
    //res +=  (n - 5 + n - (2*odd - 1)*5) / 2 * odd / 2;
    res += (n - 5*odd) * odd / 2;
  } else {
    //res += ( n/2 + (n - (2*even - 2)*5)/2) * even / 2;
    res += (n + 5 - 5*even) * even / 2;
    //res += ( (n - 6)/2 + (n - 1 - (2*odd - 1)*5)/2) * odd / 2;
    res += (n - 1 - 5*odd) * odd / 2;
  }
  res += n / 5 + 1;
  return res;
}

The above is, in accordance with the code to achieve parity distinction, where i is an even number is an even number, odd number is i is an odd number, a number equivalent to the arithmetic column.

Then follow the parity packets n, the arithmetic sequence using the summation formula, and groups can be obtained, and then the addition result.

Note: as it has been to ensure that when summing n-5i (or n-5i-1) must be an even number, so the first divided by 2 can be directly out about, but the final by 2 to remain at last, to explain the reasons before pass.

Guess you like

Origin www.cnblogs.com/deepllz/p/11490167.html